1use crate::utils::make_scalar_function;
21use arrow::array::{
22 Array, ArrayRef, FixedSizeListArray, GenericListArray, GenericListViewArray,
23 OffsetSizeTrait, UInt32Array, UInt64Array,
24};
25use arrow::buffer::{OffsetBuffer, ScalarBuffer};
26use arrow::compute::take;
27use arrow::datatypes::DataType::{
28 FixedSizeList, LargeList, LargeListView, List, ListView, Null,
29};
30use arrow::datatypes::{DataType, FieldRef};
31use datafusion_common::cast::{
32 as_fixed_size_list_array, as_large_list_array, as_large_list_view_array,
33 as_list_array, as_list_view_array,
34};
35use datafusion_common::{Result, exec_err, utils::take_function_args};
36use datafusion_expr::{
37 ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
38};
39use datafusion_macros::user_doc;
40use itertools::Itertools;
41use std::any::Any;
42use std::sync::Arc;
43
44make_udf_expr_and_func!(
45 ArrayReverse,
46 array_reverse,
47 array,
48 "reverses the order of elements in the array.",
49 array_reverse_udf
50);
51
52#[user_doc(
53 doc_section(label = "Array Functions"),
54 description = "Returns the array with the order of the elements reversed.",
55 syntax_example = "array_reverse(array)",
56 sql_example = r#"```sql
57> select array_reverse([1, 2, 3, 4]);
58+------------------------------------------------------------+
59| array_reverse(List([1, 2, 3, 4])) |
60+------------------------------------------------------------+
61| [4, 3, 2, 1] |
62+------------------------------------------------------------+
63```"#,
64 argument(
65 name = "array",
66 description = "Array expression. Can be a constant, column, or function, and any combination of array operators."
67 )
68)]
69#[derive(Debug, PartialEq, Eq, Hash)]
70pub struct ArrayReverse {
71 signature: Signature,
72 aliases: Vec<String>,
73}
74
75impl Default for ArrayReverse {
76 fn default() -> Self {
77 Self::new()
78 }
79}
80
81impl ArrayReverse {
82 pub fn new() -> Self {
83 Self {
84 signature: Signature::array(Volatility::Immutable),
85 aliases: vec!["list_reverse".to_string()],
86 }
87 }
88}
89
90impl ScalarUDFImpl for ArrayReverse {
91 fn as_any(&self) -> &dyn Any {
92 self
93 }
94
95 fn name(&self) -> &str {
96 "array_reverse"
97 }
98
99 fn signature(&self) -> &Signature {
100 &self.signature
101 }
102
103 fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
104 Ok(arg_types[0].clone())
105 }
106
107 fn invoke_with_args(
108 &self,
109 args: datafusion_expr::ScalarFunctionArgs,
110 ) -> Result<ColumnarValue> {
111 make_scalar_function(array_reverse_inner)(&args.args)
112 }
113
114 fn aliases(&self) -> &[String] {
115 &self.aliases
116 }
117
118 fn documentation(&self) -> Option<&Documentation> {
119 self.doc()
120 }
121}
122
123pub fn array_reverse_inner(arg: &[ArrayRef]) -> Result<ArrayRef> {
125 let [input_array] = take_function_args("array_reverse", arg)?;
126
127 match &input_array.data_type() {
128 List(field) => {
129 let array = as_list_array(input_array)?;
130 general_array_reverse::<i32>(array, field)
131 }
132 LargeList(field) => {
133 let array = as_large_list_array(input_array)?;
134 general_array_reverse::<i64>(array, field)
135 }
136 FixedSizeList(field, _) => {
137 let array = as_fixed_size_list_array(input_array)?;
138 fixed_size_array_reverse(array, field)
139 }
140 Null => Ok(Arc::clone(input_array)),
141 ListView(field) => {
142 let array = as_list_view_array(input_array)?;
143 list_view_reverse::<i32>(array, field)
144 }
145 LargeListView(field) => {
146 let array = as_large_list_view_array(input_array)?;
147 list_view_reverse::<i64>(array, field)
148 }
149 array_type => exec_err!("array_reverse does not support type '{array_type}'."),
150 }
151}
152
153fn general_array_reverse<O: OffsetSizeTrait>(
154 array: &GenericListArray<O>,
155 field: &FieldRef,
156) -> Result<ArrayRef> {
157 let values = array.values();
158 let mut offsets = vec![O::usize_as(0)];
159 let mut indices: Vec<O> = Vec::with_capacity(values.len());
160
161 for (row_index, (&start, &end)) in array.offsets().iter().tuple_windows().enumerate()
162 {
163 if array.is_null(row_index) {
165 offsets.push(offsets[row_index]);
166 continue;
167 }
168
169 let mut index = end - O::one();
170 while index >= start {
171 indices.push(index);
172 index = index - O::one();
173 }
174 let size = end - start;
175 offsets.push(offsets[row_index] + size);
176 }
177
178 let indices_array: ArrayRef = if O::IS_LARGE {
180 Arc::new(UInt64Array::from(
181 indices
182 .iter()
183 .map(|i| i.as_usize() as u64)
184 .collect::<Vec<_>>(),
185 ))
186 } else {
187 Arc::new(UInt32Array::from(
188 indices
189 .iter()
190 .map(|i| i.as_usize() as u32)
191 .collect::<Vec<_>>(),
192 ))
193 };
194 let values = take(&values, &indices_array, None)?;
195 Ok(Arc::new(GenericListArray::<O>::try_new(
196 Arc::clone(field),
197 OffsetBuffer::<O>::new(offsets.into()),
198 values,
199 array.nulls().cloned(),
200 )?))
201}
202
203fn list_view_reverse<O: OffsetSizeTrait>(
210 array: &GenericListViewArray<O>,
211 field: &FieldRef,
212) -> Result<ArrayRef> {
213 let offsets = array.offsets();
214 let values = array.values();
215 let sizes = array.sizes();
216
217 let mut new_offsets: Vec<O> = Vec::with_capacity(offsets.len());
218 let mut indices: Vec<O> = Vec::with_capacity(values.len());
219 let mut new_sizes = Vec::with_capacity(sizes.len());
220
221 let mut current_offset = O::zero();
222 for (row_index, offset) in offsets.iter().enumerate() {
223 new_offsets.push(current_offset);
224
225 if array.is_null(row_index) {
227 new_sizes.push(O::zero());
228 continue;
229 }
230 let size = sizes[row_index];
231 new_sizes.push(size);
232
233 let array_start = *offset;
235 let array_end = array_start + size;
236 let mut idx = array_end - O::one();
237 while idx >= array_start {
238 indices.push(idx);
239 idx = idx - O::one();
240 }
241
242 current_offset += size;
243 }
244
245 let indices_array: ArrayRef = if O::IS_LARGE {
247 Arc::new(UInt64Array::from(
248 indices
249 .iter()
250 .map(|i| i.as_usize() as u64)
251 .collect::<Vec<_>>(),
252 ))
253 } else {
254 Arc::new(UInt32Array::from(
255 indices
256 .iter()
257 .map(|i| i.as_usize() as u32)
258 .collect::<Vec<_>>(),
259 ))
260 };
261 let values = take(&values, &indices_array, None)?;
262 Ok(Arc::new(GenericListViewArray::<O>::try_new(
263 Arc::clone(field),
264 ScalarBuffer::from(new_offsets),
265 ScalarBuffer::from(new_sizes),
266 values,
267 array.nulls().cloned(),
268 )?))
269}
270
271fn fixed_size_array_reverse(
272 array: &FixedSizeListArray,
273 field: &FieldRef,
274) -> Result<ArrayRef> {
275 let values: &Arc<dyn Array> = array.values();
276
277 let mut indices: Vec<u64> = (0..values.len() as u64).collect();
280 for chunk in indices.chunks_mut(array.value_length() as usize) {
281 chunk.reverse();
282 }
283
284 let indices_array: ArrayRef = Arc::new(UInt64Array::from(indices));
286 let values = take(&values, &indices_array, None)?;
287
288 Ok(Arc::new(FixedSizeListArray::try_new(
289 Arc::clone(field),
290 array.value_length(),
291 values,
292 array.nulls().cloned(),
293 )?))
294}
295
296#[cfg(test)]
297mod tests {
298 use crate::reverse::{fixed_size_array_reverse, list_view_reverse};
299 use arrow::{
300 array::{
301 AsArray, FixedSizeListArray, GenericListViewArray, Int32Array,
302 LargeListViewArray, ListViewArray, OffsetSizeTrait,
303 },
304 buffer::{NullBuffer, ScalarBuffer},
305 datatypes::{DataType, Field, Int32Type},
306 };
307 use datafusion_common::Result;
308 use std::sync::Arc;
309
310 fn list_view_values<O: OffsetSizeTrait>(
311 array: &GenericListViewArray<O>,
312 ) -> Vec<Option<Vec<i32>>> {
313 array
314 .iter()
315 .map(|x| x.map(|x| x.as_primitive::<Int32Type>().values().to_vec()))
316 .collect()
317 }
318
319 fn fixed_size_list_values(array: &FixedSizeListArray) -> Vec<Option<Vec<i32>>> {
320 array
321 .iter()
322 .map(|x| x.map(|x| x.as_primitive::<Int32Type>().values().to_vec()))
323 .collect()
324 }
325
326 #[test]
327 fn test_reverse_list_view() -> Result<()> {
328 let field = Arc::new(Field::new("a", DataType::Int32, false));
329 let offsets = ScalarBuffer::from(vec![0, 1, 6, 6]);
330 let sizes = ScalarBuffer::from(vec![1, 5, 0, 3]);
331 let values = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]));
332 let nulls = Some(NullBuffer::from(vec![true, true, false, true]));
333 let list_view = ListViewArray::new(field, offsets, sizes, values, nulls);
334 let result = list_view_reverse(
335 &list_view,
336 &Arc::new(Field::new("test", DataType::Int32, true)),
337 )?;
338 let reversed = list_view_values(result.as_list_view::<i32>());
339 let expected = vec![
340 Some(vec![1]),
341 Some(vec![6, 5, 4, 3, 2]),
342 None,
343 Some(vec![9, 8, 7]),
344 ];
345 assert_eq!(expected, reversed);
346 Ok(())
347 }
348
349 #[test]
350 fn test_reverse_large_list_view() -> Result<()> {
351 let field = Arc::new(Field::new("a", DataType::Int32, false));
352 let offsets = ScalarBuffer::from(vec![0, 1, 6, 6]);
353 let sizes = ScalarBuffer::from(vec![1, 5, 0, 3]);
354 let values = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]));
355 let nulls = Some(NullBuffer::from(vec![true, true, false, true]));
356 let list_view = LargeListViewArray::new(field, offsets, sizes, values, nulls);
357 let result = list_view_reverse(
358 &list_view,
359 &Arc::new(Field::new("test", DataType::Int32, true)),
360 )?;
361 let reversed = list_view_values(result.as_list_view::<i64>());
362 let expected = vec![
363 Some(vec![1]),
364 Some(vec![6, 5, 4, 3, 2]),
365 None,
366 Some(vec![9, 8, 7]),
367 ];
368 assert_eq!(expected, reversed);
369 Ok(())
370 }
371
372 #[test]
373 fn test_reverse_list_view_out_of_order() -> Result<()> {
374 let field = Arc::new(Field::new("a", DataType::Int32, false));
375 let offsets = ScalarBuffer::from(vec![6, 1, 6, 0]); let sizes = ScalarBuffer::from(vec![3, 5, 0, 1]);
377 let values = Arc::new(Int32Array::from(vec![
378 1, 2, 3, 4, 5, 6, 7, 8, 9, ]));
383 let nulls = Some(NullBuffer::from(vec![true, true, false, true]));
384 let list_view = ListViewArray::new(field, offsets, sizes, values, nulls);
385 let result = list_view_reverse(
386 &list_view,
387 &Arc::new(Field::new("test", DataType::Int32, true)),
388 )?;
389 let reversed = list_view_values(result.as_list_view::<i32>());
390 let expected = vec![
391 Some(vec![9, 8, 7]),
392 Some(vec![6, 5, 4, 3, 2]),
393 None,
394 Some(vec![1]),
395 ];
396 assert_eq!(expected, reversed);
397 Ok(())
398 }
399
400 #[test]
401 fn test_reverse_list_view_with_nulls() -> Result<()> {
402 let field = Arc::new(Field::new("a", DataType::Int32, false));
403 let offsets = ScalarBuffer::from(vec![16, 1, 6, 0]); let sizes = ScalarBuffer::from(vec![3, 5, 10, 1]);
405 let values = Arc::new(Int32Array::from(vec![
406 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7, 8, 9, ]));
411 let nulls = Some(NullBuffer::from(vec![true, true, false, true]));
412 let list_view = ListViewArray::new(field, offsets, sizes, values, nulls);
413 let result = list_view_reverse(
414 &list_view,
415 &Arc::new(Field::new("test", DataType::Int32, true)),
416 )?;
417 let reversed = list_view_values(result.as_list_view::<i32>());
418 let expected = vec![
419 Some(vec![9, 8, 7]),
420 Some(vec![6, 5, 4, 3, 2]),
421 None,
422 Some(vec![1]),
423 ];
424 assert_eq!(expected, reversed);
425 Ok(())
426 }
427
428 #[test]
429 fn test_reverse_list_view_empty() -> Result<()> {
430 let field = Arc::new(Field::new("a", DataType::Int32, false));
431 let offsets = ScalarBuffer::from(vec![]);
432 let sizes = ScalarBuffer::from(vec![]);
433 let empty_array: Vec<i32> = vec![];
434 let values = Arc::new(Int32Array::from(empty_array));
435 let nulls = None;
436 let list_view = ListViewArray::new(field, offsets, sizes, values, nulls);
437 let result = list_view_reverse(
438 &list_view,
439 &Arc::new(Field::new("test", DataType::Int32, true)),
440 )?;
441 let reversed = list_view_values(result.as_list_view::<i32>());
442 let expected: Vec<Option<Vec<i32>>> = vec![];
443 assert_eq!(expected, reversed);
444 Ok(())
445 }
446
447 #[test]
448 fn test_reverse_list_view_all_nulls() -> Result<()> {
449 let field = Arc::new(Field::new("a", DataType::Int32, false));
450 let offsets = ScalarBuffer::from(vec![0, 1, 2, 3]);
451 let sizes = ScalarBuffer::from(vec![0, 1, 1, 1]);
452 let values = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
453 let nulls = Some(NullBuffer::from(vec![false, false, false, false]));
454 let list_view = ListViewArray::new(field, offsets, sizes, values, nulls);
455 let result = list_view_reverse(
456 &list_view,
457 &Arc::new(Field::new("test", DataType::Int32, true)),
458 )?;
459 let reversed = list_view_values(result.as_list_view::<i32>());
460 let expected: Vec<Option<Vec<i32>>> = vec![None, None, None, None];
461 assert_eq!(expected, reversed);
462 Ok(())
463 }
464
465 #[test]
466 fn test_reverse_fixed_size_list() -> Result<()> {
467 let field = Arc::new(Field::new("a", DataType::Int32, false));
468 let values = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]));
469 let result = fixed_size_array_reverse(
470 &FixedSizeListArray::new(
471 field,
472 3,
473 values,
474 Some(NullBuffer::from(vec![true, false, true])),
475 ),
476 &Arc::new(Field::new("test", DataType::Int32, true)),
477 )?;
478 let reversed = fixed_size_list_values(result.as_fixed_size_list());
479 let expected = vec![Some(vec![3, 2, 1]), None, Some(vec![9, 8, 7])];
480 assert_eq!(expected, reversed);
481 Ok(())
482 }
483
484 #[test]
485 fn test_reverse_fixed_size_list_empty() -> Result<()> {
486 let field = Arc::new(Field::new("a", DataType::Int32, false));
487 let empty_array: Vec<i32> = vec![];
488 let values = Arc::new(Int32Array::from(empty_array));
489 let nulls = None;
490 let fixed_size_list = FixedSizeListArray::new(field, 3, values, nulls);
491 let result = fixed_size_array_reverse(
492 &fixed_size_list,
493 &Arc::new(Field::new("test", DataType::Int32, true)),
494 )?;
495 let reversed = fixed_size_list_values(result.as_fixed_size_list());
496 let expected: Vec<Option<Vec<i32>>> = vec![];
497 assert_eq!(expected, reversed);
498 Ok(())
499 }
500}