1use std::sync::Arc;
5
6use arrow_array::{Array, RecordBatch, make_array};
7use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer};
8use arrow_data::{ArrayData, ArrayDataBuilder, transform::MutableArrayData};
9use arrow_schema::DataType;
10
11pub fn deep_copy_buffer(buffer: &Buffer) -> Buffer {
12 Buffer::from(buffer.as_slice())
13}
14
15pub fn deep_copy_nulls(nulls: Option<&NullBuffer>) -> Option<NullBuffer> {
16 let nulls = nulls?;
17 let bit_buffer = deep_copy_buffer(nulls.inner().inner());
18 Some(unsafe {
28 NullBuffer::new_unchecked(
29 BooleanBuffer::new(bit_buffer, nulls.offset(), nulls.len()),
30 nulls.null_count(),
31 )
32 })
33}
34
35pub fn deep_copy_array_data(data: &ArrayData) -> ArrayData {
36 let data_type = data.data_type().clone();
37 let len = data.len();
38 let nulls = deep_copy_nulls(data.nulls());
39 let offset = data.offset();
40 let buffers = data
41 .buffers()
42 .iter()
43 .map(deep_copy_buffer)
44 .collect::<Vec<_>>();
45 let child_data = data
46 .child_data()
47 .iter()
48 .map(deep_copy_array_data)
49 .collect::<Vec<_>>();
50 unsafe {
64 ArrayDataBuilder::new(data_type)
65 .len(len)
66 .nulls(nulls)
67 .offset(offset)
68 .buffers(buffers)
69 .child_data(child_data)
70 .build_unchecked()
71 }
72}
73
74pub fn deep_copy_array(array: &dyn Array) -> Arc<dyn Array> {
75 let data = array.to_data();
76 let data = deep_copy_array_data(&data);
77 make_array(data)
78}
79
80pub fn deep_copy_batch(batch: &RecordBatch) -> crate::Result<RecordBatch> {
81 let arrays = batch
82 .columns()
83 .iter()
84 .map(|array| deep_copy_array(array))
85 .collect::<Vec<_>>();
86 RecordBatch::try_new(batch.schema(), arrays)
87}
88
89pub fn deep_copy_array_data_sliced(data: &ArrayData) -> ArrayData {
92 let mut mutable = MutableArrayData::new(vec![data], false, data.len());
94
95 let start = match data.data_type() {
103 DataType::Boolean => 0,
104 _ => data.offset(),
105 };
106 mutable.extend(0, start, start + data.len());
107
108 mutable.freeze()
110}
111
112pub fn deep_copy_array_sliced(array: &dyn Array) -> Arc<dyn Array> {
114 let data = array.to_data();
115 let data = deep_copy_array_data_sliced(&data);
116 make_array(data)
117}
118
119pub fn deep_copy_batch_sliced(batch: &RecordBatch) -> crate::Result<RecordBatch> {
121 let arrays = batch
122 .columns()
123 .iter()
124 .map(|array| deep_copy_array_sliced(array))
125 .collect::<Vec<_>>();
126 RecordBatch::try_new(batch.schema(), arrays)
127}
128
129#[cfg(test)]
130mod tests {
131 use std::sync::Arc;
132
133 use arrow_array::{Array, BooleanArray, Int32Array, RecordBatch, StringArray};
134 use arrow_data::ArrayDataBuilder;
135 use arrow_schema::{DataType, Field, Schema};
136
137 #[test]
138 fn raw_sliced_fixed_size_list_data_keeps_its_child_offset() {
139 let child = Int32Array::from(vec![10, 11, 20, 21]).to_data();
146 let field = Arc::new(Field::new_list_field(DataType::Int32, false));
147 let data = ArrayDataBuilder::new(DataType::FixedSizeList(field, 2))
148 .len(2)
149 .add_child_data(child)
150 .build()
151 .unwrap();
152 let sliced = data.slice(1, 1);
153
154 let copied = super::deep_copy_array_data_sliced(&sliced);
155 let copied_child = Int32Array::from(copied.child_data()[0].clone());
156 assert_eq!(copied_child.values().as_ref(), &[20, 21]);
157 }
158
159 #[test]
160 fn raw_sliced_struct_of_fixed_size_list_reaches_the_right_values() {
161 let values = Int32Array::from(vec![10, 11, 20, 21, 30, 31]).to_data();
166 let item = Arc::new(Field::new_list_field(DataType::Int32, false));
167 let list = ArrayDataBuilder::new(DataType::FixedSizeList(item, 2))
168 .len(3)
169 .add_child_data(values)
170 .build()
171 .unwrap();
172 let field = Arc::new(Field::new("l", list.data_type().clone(), false));
173 let data = ArrayDataBuilder::new(DataType::Struct(vec![field].into()))
174 .len(3)
175 .add_child_data(list)
176 .build()
177 .unwrap();
178 let sliced = data.slice(2, 1);
179
180 let copied = super::deep_copy_array_data_sliced(&sliced);
181 let copied_values = Int32Array::from(copied.child_data()[0].child_data()[0].clone());
182 assert_eq!(copied_values.values().as_ref(), &[30, 31]);
183 }
184
185 #[test]
186 fn raw_parent_offset_struct_keeps_the_selected_child_row() {
187 let field = Arc::new(Field::new("a", DataType::Int32, false));
191 let data = ArrayDataBuilder::new(DataType::Struct(vec![field].into()))
192 .len(1)
193 .offset(1)
194 .add_child_data(Int32Array::from(vec![10, 20]).to_data())
195 .build()
196 .unwrap();
197
198 let copied = super::deep_copy_array_data_sliced(&data);
199 let copied_child = Int32Array::from(copied.child_data()[0].clone());
200 assert_eq!(copied_child.values().as_ref(), &[20]);
201 }
202
203 #[test]
204 fn sliced_boolean_deep_copy_reads_from_the_slice() {
205 let array = BooleanArray::from(vec![true, false, true, false, true, false, true, false]);
210 for (offset, len) in [(0usize, 8usize), (1, 7), (3, 5), (7, 1)] {
211 let sliced = array.slice(offset, len);
212 let copied = super::deep_copy_array_sliced(&sliced);
213 let copied = copied.as_any().downcast_ref::<BooleanArray>().unwrap();
214 let expected: Vec<bool> = (0..len).map(|i| sliced.value(i)).collect();
215 let actual: Vec<bool> = (0..len).map(|i| copied.value(i)).collect();
216 assert_eq!(actual, expected, "offset={offset} len={len}");
217 }
218 }
219
220 #[test]
221 fn sliced_boolean_deep_copy_keeps_its_nulls() {
222 let array = BooleanArray::from(vec![
223 Some(true),
224 None,
225 Some(false),
226 Some(true),
227 None,
228 Some(false),
229 ]);
230 let sliced = array.slice(1, 4);
231 let copied = super::deep_copy_array_sliced(&sliced);
232 let copied = copied.as_any().downcast_ref::<BooleanArray>().unwrap();
233 let expected: Vec<Option<bool>> = (0..sliced.len())
234 .map(|i| (!sliced.is_null(i)).then(|| sliced.value(i)))
235 .collect();
236 let actual: Vec<Option<bool>> = (0..copied.len())
237 .map(|i| (!copied.is_null(i)).then(|| copied.value(i)))
238 .collect();
239 assert_eq!(actual, expected);
240 }
241
242 #[test]
243 fn test_deep_copy_sliced_array_with_nulls() {
244 let array = Arc::new(Int32Array::from(vec![
245 Some(1),
246 None,
247 Some(3),
248 None,
249 Some(5),
250 ]));
251 let sliced_array = array.slice(1, 3);
252 let copied_array = super::deep_copy_array(&sliced_array);
253 assert_eq!(sliced_array.len(), copied_array.len());
254 assert_eq!(sliced_array.nulls(), copied_array.nulls());
255 }
256
257 #[test]
258 fn test_deep_copy_array_data_sliced() {
259 let array = Int32Array::from((0..1000).collect::<Vec<i32>>());
260 let sliced = array.slice(100, 10);
261
262 let sliced_data = sliced.to_data();
263 let copied_data = super::deep_copy_array_data_sliced(&sliced_data);
264
265 assert_eq!(copied_data.len(), 10);
266 assert_eq!(copied_data.offset(), 0);
267
268 let copied_array = Int32Array::from(copied_data);
270 for i in 0..10 {
271 assert_eq!(copied_array.value(i), 100 + i as i32);
272 }
273 }
274
275 #[test]
276 fn test_deep_copy_array_sliced() {
277 let array = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
278 let sliced = array.slice(1, 3);
279
280 let copied = super::deep_copy_array_sliced(&sliced);
281
282 assert_eq!(copied.len(), 3);
283 let copied_int = copied.as_any().downcast_ref::<Int32Array>().unwrap();
284 assert_eq!(copied_int.value(0), 2);
285 assert_eq!(copied_int.value(1), 3);
286 assert_eq!(copied_int.value(2), 4);
287 }
288
289 #[test]
290 fn test_deep_copy_batch_sliced() {
291 let schema = Arc::new(Schema::new(vec![
292 Field::new("id", DataType::Int32, false),
293 Field::new("name", DataType::Utf8, false),
294 ]));
295
296 let id_array = Arc::new(Int32Array::from((0..100).collect::<Vec<i32>>()));
297 let name_array = Arc::new(StringArray::from(
298 (0..100)
299 .map(|i| format!("name_{}", i))
300 .collect::<Vec<String>>(),
301 ));
302
303 let batch = RecordBatch::try_new(
304 schema,
305 vec![id_array as Arc<dyn Array>, name_array as Arc<dyn Array>],
306 )
307 .unwrap();
308
309 let sliced = batch.slice(10, 5);
310 let copied = super::deep_copy_batch_sliced(&sliced).unwrap();
311
312 assert_eq!(copied.num_rows(), 5);
313 assert_eq!(copied.num_columns(), 2);
314
315 let id_col = copied
317 .column(0)
318 .as_any()
319 .downcast_ref::<Int32Array>()
320 .unwrap();
321 let name_col = copied
322 .column(1)
323 .as_any()
324 .downcast_ref::<StringArray>()
325 .unwrap();
326
327 for i in 0..5 {
328 assert_eq!(id_col.value(i), 10 + i as i32);
329 assert_eq!(name_col.value(i), format!("name_{}", 10 + i));
330 }
331 }
332
333 #[test]
334 fn test_deep_copy_array_sliced_with_nulls() {
335 let array = Arc::new(Int32Array::from(vec![
336 Some(1),
337 None,
338 Some(3),
339 None,
340 Some(5),
341 ]));
342 let sliced = array.slice(1, 3); let copied = super::deep_copy_array_sliced(&sliced);
345
346 assert_eq!(copied.len(), 3);
347 assert_eq!(copied.null_count(), 2); let copied_int = copied.as_any().downcast_ref::<Int32Array>().unwrap();
350 assert!(!copied_int.is_valid(0)); assert!(copied_int.is_valid(1)); assert!(!copied_int.is_valid(2)); assert_eq!(copied_int.value(1), 3);
354 }
355}