From 78bb64e03d71214b073cef4d183a3f7c6c52373c Mon Sep 17 00:00:00 2001 From: Eren Avsarogullari Date: Tue, 12 Mar 2024 23:18:49 -0700 Subject: [PATCH] Issue-9565 - Port ArrayRepeat to function-arrays subcrate (#9568) --- datafusion/expr/src/built_in_function.rs | 10 -- datafusion/expr/src/expr_fn.rs | 7 - datafusion/functions-array/src/kernels.rs | 153 +++++++++++++++++- datafusion/functions-array/src/lib.rs | 2 + datafusion/functions-array/src/udf.rs | 61 ++++++- .../physical-expr/src/array_expressions.rs | 146 ----------------- datafusion/physical-expr/src/functions.rs | 3 - datafusion/proto/proto/datafusion.proto | 2 +- datafusion/proto/src/generated/pbjson.rs | 3 - datafusion/proto/src/generated/prost.rs | 4 +- .../proto/src/logical_plan/from_proto.rs | 11 +- datafusion/proto/src/logical_plan/to_proto.rs | 1 - .../tests/cases/roundtrip_logical_plan.rs | 1 + 13 files changed, 215 insertions(+), 189 deletions(-) diff --git a/datafusion/expr/src/built_in_function.rs b/datafusion/expr/src/built_in_function.rs index 6435eaee160a..f9725a5514d3 100644 --- a/datafusion/expr/src/built_in_function.rs +++ b/datafusion/expr/src/built_in_function.rs @@ -122,8 +122,6 @@ pub enum BuiltinScalarFunction { ArrayRemoveN, /// array_remove_all ArrayRemoveAll, - /// array_repeat - ArrayRepeat, /// array_replace ArrayReplace, /// array_replace_n @@ -323,7 +321,6 @@ impl BuiltinScalarFunction { BuiltinScalarFunction::ArrayPopBack => Volatility::Immutable, BuiltinScalarFunction::ArrayPosition => Volatility::Immutable, BuiltinScalarFunction::ArrayPositions => Volatility::Immutable, - BuiltinScalarFunction::ArrayRepeat => Volatility::Immutable, BuiltinScalarFunction::ArrayRemove => Volatility::Immutable, BuiltinScalarFunction::ArrayRemoveN => Volatility::Immutable, BuiltinScalarFunction::ArrayRemoveAll => Volatility::Immutable, @@ -421,11 +418,6 @@ impl BuiltinScalarFunction { BuiltinScalarFunction::ArrayPositions => { Ok(List(Arc::new(Field::new("item", UInt64, true)))) } - BuiltinScalarFunction::ArrayRepeat => Ok(List(Arc::new(Field::new( - "item", - input_expr_types[0].clone(), - true, - )))), BuiltinScalarFunction::ArrayRemove => Ok(input_expr_types[0].clone()), BuiltinScalarFunction::ArrayRemoveN => Ok(input_expr_types[0].clone()), BuiltinScalarFunction::ArrayRemoveAll => Ok(input_expr_types[0].clone()), @@ -652,7 +644,6 @@ impl BuiltinScalarFunction { BuiltinScalarFunction::ArrayPositions => { Signature::array_and_element(self.volatility()) } - BuiltinScalarFunction::ArrayRepeat => Signature::any(2, self.volatility()), BuiltinScalarFunction::ArrayRemove => { Signature::array_and_element(self.volatility()) } @@ -1075,7 +1066,6 @@ impl BuiltinScalarFunction { BuiltinScalarFunction::ArrayPositions => { &["array_positions", "list_positions"] } - BuiltinScalarFunction::ArrayRepeat => &["array_repeat", "list_repeat"], BuiltinScalarFunction::ArrayRemove => &["array_remove", "list_remove"], BuiltinScalarFunction::ArrayRemoveN => &["array_remove_n", "list_remove_n"], BuiltinScalarFunction::ArrayRemoveAll => { diff --git a/datafusion/expr/src/expr_fn.rs b/datafusion/expr/src/expr_fn.rs index 12eafa6ccdbc..56833d452f19 100644 --- a/datafusion/expr/src/expr_fn.rs +++ b/datafusion/expr/src/expr_fn.rs @@ -622,12 +622,6 @@ scalar_expr!( array element, "searches for an element in the array, returns all occurrences." ); -scalar_expr!( - ArrayRepeat, - array_repeat, - element count, - "returns an array containing element `count` times." -); scalar_expr!( ArrayRemove, array_remove, @@ -1270,7 +1264,6 @@ mod test { test_scalar_expr!(ArrayPopBack, array_pop_back, array); test_scalar_expr!(ArrayPosition, array_position, array, element, index); test_scalar_expr!(ArrayPositions, array_positions, array, element); - test_scalar_expr!(ArrayRepeat, array_repeat, element, count); test_scalar_expr!(ArrayRemove, array_remove, array, element); test_scalar_expr!(ArrayRemoveN, array_remove_n, array, element, max); test_scalar_expr!(ArrayRemoveAll, array_remove_all, array, element); diff --git a/datafusion/functions-array/src/kernels.rs b/datafusion/functions-array/src/kernels.rs index 4ac32c02af78..1a6ebdd9029d 100644 --- a/datafusion/functions-array/src/kernels.rs +++ b/datafusion/functions-array/src/kernels.rs @@ -18,16 +18,17 @@ //! implementation kernels for array functions use arrow::array::{ - Array, ArrayRef, BooleanArray, Date32Array, Float32Array, Float64Array, + Array, ArrayRef, BooleanArray, Capacities, Date32Array, Float32Array, Float64Array, GenericListArray, Int16Array, Int32Array, Int64Array, Int8Array, LargeListArray, - LargeStringArray, ListArray, ListBuilder, OffsetSizeTrait, StringArray, - StringBuilder, UInt16Array, UInt32Array, UInt64Array, UInt8Array, + LargeStringArray, ListArray, ListBuilder, MutableArrayData, OffsetSizeTrait, + StringArray, StringBuilder, UInt16Array, UInt32Array, UInt64Array, UInt8Array, }; use arrow::compute; use arrow::datatypes::{ DataType, Date32Type, Field, IntervalMonthDayNanoType, UInt64Type, }; use arrow::row::{RowConverter, SortField}; +use arrow_array::new_null_array; use arrow_buffer::{BooleanBufferBuilder, NullBuffer, OffsetBuffer}; use arrow_schema::FieldRef; use arrow_schema::SortOptions; @@ -733,6 +734,152 @@ fn general_array_length(array: &[ArrayRef]) -> Result Result { + if args.len() != 2 { + return exec_err!("array_repeat expects two arguments"); + } + + let element = &args[0]; + let count_array = as_int64_array(&args[1])?; + + match element.data_type() { + DataType::List(_) => { + let list_array = as_list_array(element)?; + general_list_repeat::(list_array, count_array) + } + DataType::LargeList(_) => { + let list_array = as_large_list_array(element)?; + general_list_repeat::(list_array, count_array) + } + _ => general_repeat::(element, count_array), + } +} + +/// For each element of `array[i]` repeat `count_array[i]` times. +/// +/// Assumption for the input: +/// 1. `count[i] >= 0` +/// 2. `array.len() == count_array.len()` +/// +/// For example, +/// ```text +/// array_repeat( +/// [1, 2, 3], [2, 0, 1] => [[1, 1], [], [3]] +/// ) +/// ``` +fn general_repeat( + array: &ArrayRef, + count_array: &Int64Array, +) -> Result { + let data_type = array.data_type(); + let mut new_values = vec![]; + + let count_vec = count_array + .values() + .to_vec() + .iter() + .map(|x| *x as usize) + .collect::>(); + + for (row_index, &count) in count_vec.iter().enumerate() { + let repeated_array = if array.is_null(row_index) { + new_null_array(data_type, count) + } else { + let original_data = array.to_data(); + let capacity = Capacities::Array(count); + let mut mutable = + MutableArrayData::with_capacities(vec![&original_data], false, capacity); + + for _ in 0..count { + mutable.extend(0, row_index, row_index + 1); + } + + let data = mutable.freeze(); + arrow_array::make_array(data) + }; + new_values.push(repeated_array); + } + + let new_values: Vec<_> = new_values.iter().map(|a| a.as_ref()).collect(); + let values = compute::concat(&new_values)?; + + Ok(Arc::new(GenericListArray::::try_new( + Arc::new(Field::new("item", data_type.to_owned(), true)), + OffsetBuffer::from_lengths(count_vec), + values, + None, + )?)) +} + +/// Handle List version of `general_repeat` +/// +/// For each element of `list_array[i]` repeat `count_array[i]` times. +/// +/// For example, +/// ```text +/// array_repeat( +/// [[1, 2, 3], [4, 5], [6]], [2, 0, 1] => [[[1, 2, 3], [1, 2, 3]], [], [[6]]] +/// ) +/// ``` +fn general_list_repeat( + list_array: &GenericListArray, + count_array: &Int64Array, +) -> Result { + let data_type = list_array.data_type(); + let value_type = list_array.value_type(); + let mut new_values = vec![]; + + let count_vec = count_array + .values() + .to_vec() + .iter() + .map(|x| *x as usize) + .collect::>(); + + for (list_array_row, &count) in list_array.iter().zip(count_vec.iter()) { + let list_arr = match list_array_row { + Some(list_array_row) => { + let original_data = list_array_row.to_data(); + let capacity = Capacities::Array(original_data.len() * count); + let mut mutable = MutableArrayData::with_capacities( + vec![&original_data], + false, + capacity, + ); + + for _ in 0..count { + mutable.extend(0, 0, original_data.len()); + } + + let data = mutable.freeze(); + let repeated_array = arrow_array::make_array(data); + + let list_arr = GenericListArray::::try_new( + Arc::new(Field::new("item", value_type.clone(), true)), + OffsetBuffer::::from_lengths(vec![original_data.len(); count]), + repeated_array, + None, + )?; + Arc::new(list_arr) as ArrayRef + } + None => new_null_array(data_type, count), + }; + new_values.push(list_arr); + } + + let lengths = new_values.iter().map(|a| a.len()).collect::>(); + let new_values: Vec<_> = new_values.iter().map(|a| a.as_ref()).collect(); + let values = compute::concat(&new_values)?; + + Ok(Arc::new(ListArray::try_new( + Arc::new(Field::new("item", data_type.to_owned(), true)), + OffsetBuffer::::from_lengths(lengths), + values, + None, + )?)) +} + /// Array_length SQL function pub fn array_length(args: &[ArrayRef]) -> Result { if args.len() != 1 && args.len() != 2 { diff --git a/datafusion/functions-array/src/lib.rs b/datafusion/functions-array/src/lib.rs index 95143570cc5f..31b971a42297 100644 --- a/datafusion/functions-array/src/lib.rs +++ b/datafusion/functions-array/src/lib.rs @@ -55,6 +55,7 @@ pub mod expr_fn { pub use super::udf::array_empty; pub use super::udf::array_length; pub use super::udf::array_ndims; + pub use super::udf::array_repeat; pub use super::udf::array_sort; pub use super::udf::array_to_string; pub use super::udf::cardinality; @@ -86,6 +87,7 @@ pub fn register_all(registry: &mut dyn FunctionRegistry) -> Result<()> { udf::flatten_udf(), udf::array_sort_udf(), udf::array_distinct_udf(), + udf::array_repeat_udf(), ]; functions.into_iter().try_for_each(|udf| { let existing_udf = registry.register_udf(udf)?; diff --git a/datafusion/functions-array/src/udf.rs b/datafusion/functions-array/src/udf.rs index 02cacf86b0a0..9fd9e0309bde 100644 --- a/datafusion/functions-array/src/udf.rs +++ b/datafusion/functions-array/src/udf.rs @@ -21,6 +21,7 @@ use arrow::array::{NullArray, StringArray}; use arrow::datatypes::DataType; use arrow::datatypes::Field; use arrow::datatypes::IntervalUnit::MonthDayNano; +use arrow_schema::DataType::{LargeUtf8, List, Utf8}; use datafusion_common::exec_err; use datafusion_common::plan_err; use datafusion_common::Result; @@ -126,7 +127,7 @@ impl ScalarUDFImpl for StringToArray { &self.signature } - fn return_type(&self, arg_types: &[DataType]) -> datafusion_common::Result { + fn return_type(&self, arg_types: &[DataType]) -> Result { use DataType::*; Ok(match arg_types[0] { Utf8 | LargeUtf8 => { @@ -140,7 +141,7 @@ impl ScalarUDFImpl for StringToArray { }) } - fn invoke(&self, args: &[ColumnarValue]) -> datafusion_common::Result { + fn invoke(&self, args: &[ColumnarValue]) -> Result { let mut args = ColumnarValue::values_to_arrays(args)?; // Case: delimiter is NULL, needs to be handled as well. if args[1].as_any().is::() { @@ -148,10 +149,10 @@ impl ScalarUDFImpl for StringToArray { }; match args[0].data_type() { - arrow::datatypes::DataType::Utf8 => { + Utf8 => { crate::kernels::string_to_array::(&args).map(ColumnarValue::Array) } - arrow::datatypes::DataType::LargeUtf8 => { + LargeUtf8 => { crate::kernels::string_to_array::(&args).map(ColumnarValue::Array) } other => { @@ -588,6 +589,58 @@ impl ScalarUDFImpl for ArrayEmpty { } } +make_udf_function!( + ArrayRepeat, + array_repeat, + element count, // arg name + "returns an array containing element `count` times.", // doc + array_repeat_udf // internal function name +); +#[derive(Debug)] +pub(super) struct ArrayRepeat { + signature: Signature, + aliases: Vec, +} + +impl ArrayRepeat { + pub fn new() -> Self { + Self { + signature: Signature::variadic_any(Volatility::Immutable), + aliases: vec![String::from("array_repeat"), String::from("list_repeat")], + } + } +} + +impl ScalarUDFImpl for ArrayRepeat { + fn as_any(&self) -> &dyn Any { + self + } + fn name(&self) -> &str { + "array_repeat" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, arg_types: &[DataType]) -> Result { + Ok(List(Arc::new(Field::new( + "item", + arg_types[0].clone(), + true, + )))) + } + + fn invoke(&self, args: &[ColumnarValue]) -> Result { + let args = ColumnarValue::values_to_arrays(args)?; + crate::kernels::array_repeat(&args).map(ColumnarValue::Array) + } + + fn aliases(&self) -> &[String] { + &self.aliases + } +} + make_udf_function!( ArrayLength, array_length, diff --git a/datafusion/physical-expr/src/array_expressions.rs b/datafusion/physical-expr/src/array_expressions.rs index 29ef9d10faef..c846674e752f 100644 --- a/datafusion/physical-expr/src/array_expressions.rs +++ b/datafusion/physical-expr/src/array_expressions.rs @@ -745,152 +745,6 @@ pub fn array_pop_back(args: &[ArrayRef]) -> Result { } } -/// Array_repeat SQL function -pub fn array_repeat(args: &[ArrayRef]) -> Result { - if args.len() != 2 { - return exec_err!("array_repeat expects two arguments"); - } - - let element = &args[0]; - let count_array = as_int64_array(&args[1])?; - - match element.data_type() { - DataType::List(_) => { - let list_array = as_list_array(element)?; - general_list_repeat::(list_array, count_array) - } - DataType::LargeList(_) => { - let list_array = as_large_list_array(element)?; - general_list_repeat::(list_array, count_array) - } - _ => general_repeat::(element, count_array), - } -} - -/// For each element of `array[i]` repeat `count_array[i]` times. -/// -/// Assumption for the input: -/// 1. `count[i] >= 0` -/// 2. `array.len() == count_array.len()` -/// -/// For example, -/// ```text -/// array_repeat( -/// [1, 2, 3], [2, 0, 1] => [[1, 1], [], [3]] -/// ) -/// ``` -fn general_repeat( - array: &ArrayRef, - count_array: &Int64Array, -) -> Result { - let data_type = array.data_type(); - let mut new_values = vec![]; - - let count_vec = count_array - .values() - .to_vec() - .iter() - .map(|x| *x as usize) - .collect::>(); - - for (row_index, &count) in count_vec.iter().enumerate() { - let repeated_array = if array.is_null(row_index) { - new_null_array(data_type, count) - } else { - let original_data = array.to_data(); - let capacity = Capacities::Array(count); - let mut mutable = - MutableArrayData::with_capacities(vec![&original_data], false, capacity); - - for _ in 0..count { - mutable.extend(0, row_index, row_index + 1); - } - - let data = mutable.freeze(); - arrow_array::make_array(data) - }; - new_values.push(repeated_array); - } - - let new_values: Vec<_> = new_values.iter().map(|a| a.as_ref()).collect(); - let values = compute::concat(&new_values)?; - - Ok(Arc::new(GenericListArray::::try_new( - Arc::new(Field::new("item", data_type.to_owned(), true)), - OffsetBuffer::from_lengths(count_vec), - values, - None, - )?)) -} - -/// Handle List version of `general_repeat` -/// -/// For each element of `list_array[i]` repeat `count_array[i]` times. -/// -/// For example, -/// ```text -/// array_repeat( -/// [[1, 2, 3], [4, 5], [6]], [2, 0, 1] => [[[1, 2, 3], [1, 2, 3]], [], [[6]]] -/// ) -/// ``` -fn general_list_repeat( - list_array: &GenericListArray, - count_array: &Int64Array, -) -> Result { - let data_type = list_array.data_type(); - let value_type = list_array.value_type(); - let mut new_values = vec![]; - - let count_vec = count_array - .values() - .to_vec() - .iter() - .map(|x| *x as usize) - .collect::>(); - - for (list_array_row, &count) in list_array.iter().zip(count_vec.iter()) { - let list_arr = match list_array_row { - Some(list_array_row) => { - let original_data = list_array_row.to_data(); - let capacity = Capacities::Array(original_data.len() * count); - let mut mutable = MutableArrayData::with_capacities( - vec![&original_data], - false, - capacity, - ); - - for _ in 0..count { - mutable.extend(0, 0, original_data.len()); - } - - let data = mutable.freeze(); - let repeated_array = arrow_array::make_array(data); - - let list_arr = GenericListArray::::try_new( - Arc::new(Field::new("item", value_type.clone(), true)), - OffsetBuffer::::from_lengths(vec![original_data.len(); count]), - repeated_array, - None, - )?; - Arc::new(list_arr) as ArrayRef - } - None => new_null_array(data_type, count), - }; - new_values.push(list_arr); - } - - let lengths = new_values.iter().map(|a| a.len()).collect::>(); - let new_values: Vec<_> = new_values.iter().map(|a| a.as_ref()).collect(); - let values = compute::concat(&new_values)?; - - Ok(Arc::new(ListArray::try_new( - Arc::new(Field::new("item", data_type.to_owned(), true)), - OffsetBuffer::::from_lengths(lengths), - values, - None, - )?)) -} - /// Array_position SQL function pub fn array_position(args: &[ArrayRef]) -> Result { if args.len() < 2 || args.len() > 3 { diff --git a/datafusion/physical-expr/src/functions.rs b/datafusion/physical-expr/src/functions.rs index 5d13f945692a..2ac98a155322 100644 --- a/datafusion/physical-expr/src/functions.rs +++ b/datafusion/physical-expr/src/functions.rs @@ -318,9 +318,6 @@ pub fn create_physical_fun( BuiltinScalarFunction::ArrayPositions => Arc::new(|args| { make_scalar_function_inner(array_expressions::array_positions)(args) }), - BuiltinScalarFunction::ArrayRepeat => Arc::new(|args| { - make_scalar_function_inner(array_expressions::array_repeat)(args) - }), BuiltinScalarFunction::ArrayRemove => Arc::new(|args| { make_scalar_function_inner(array_expressions::array_remove)(args) }), diff --git a/datafusion/proto/proto/datafusion.proto b/datafusion/proto/proto/datafusion.proto index bd4d8b45b152..2378ff524309 100644 --- a/datafusion/proto/proto/datafusion.proto +++ b/datafusion/proto/proto/datafusion.proto @@ -630,7 +630,7 @@ enum ScalarFunction { // 86 was ArrayAppend // 87 was ArrayConcat // 88 was ArrayDims - ArrayRepeat = 89; + // 89 was ArrayRepeat // 90 was ArrayLength // 91 was ArrayNdims ArrayPosition = 92; diff --git a/datafusion/proto/src/generated/pbjson.rs b/datafusion/proto/src/generated/pbjson.rs index aaa0764b1e83..37cc1a45785b 100644 --- a/datafusion/proto/src/generated/pbjson.rs +++ b/datafusion/proto/src/generated/pbjson.rs @@ -23180,7 +23180,6 @@ impl serde::Serialize for ScalarFunction { Self::Factorial => "Factorial", Self::Lcm => "Lcm", Self::Gcd => "Gcd", - Self::ArrayRepeat => "ArrayRepeat", Self::ArrayPosition => "ArrayPosition", Self::ArrayPositions => "ArrayPositions", Self::ArrayRemove => "ArrayRemove", @@ -23288,7 +23287,6 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction { "Factorial", "Lcm", "Gcd", - "ArrayRepeat", "ArrayPosition", "ArrayPositions", "ArrayRemove", @@ -23425,7 +23423,6 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction { "Factorial" => Ok(ScalarFunction::Factorial), "Lcm" => Ok(ScalarFunction::Lcm), "Gcd" => Ok(ScalarFunction::Gcd), - "ArrayRepeat" => Ok(ScalarFunction::ArrayRepeat), "ArrayPosition" => Ok(ScalarFunction::ArrayPosition), "ArrayPositions" => Ok(ScalarFunction::ArrayPositions), "ArrayRemove" => Ok(ScalarFunction::ArrayRemove), diff --git a/datafusion/proto/src/generated/prost.rs b/datafusion/proto/src/generated/prost.rs index 07a0f30a2f68..c557fb48b191 100644 --- a/datafusion/proto/src/generated/prost.rs +++ b/datafusion/proto/src/generated/prost.rs @@ -2932,7 +2932,7 @@ pub enum ScalarFunction { /// 86 was ArrayAppend /// 87 was ArrayConcat /// 88 was ArrayDims - ArrayRepeat = 89, + /// 89 was ArrayRepeat /// 90 was ArrayLength /// 91 was ArrayNdims ArrayPosition = 92, @@ -3058,7 +3058,6 @@ impl ScalarFunction { ScalarFunction::Factorial => "Factorial", ScalarFunction::Lcm => "Lcm", ScalarFunction::Gcd => "Gcd", - ScalarFunction::ArrayRepeat => "ArrayRepeat", ScalarFunction::ArrayPosition => "ArrayPosition", ScalarFunction::ArrayPositions => "ArrayPositions", ScalarFunction::ArrayRemove => "ArrayRemove", @@ -3160,7 +3159,6 @@ impl ScalarFunction { "Factorial" => Some(Self::Factorial), "Lcm" => Some(Self::Lcm), "Gcd" => Some(Self::Gcd), - "ArrayRepeat" => Some(Self::ArrayRepeat), "ArrayPosition" => Some(Self::ArrayPosition), "ArrayPositions" => Some(Self::ArrayPositions), "ArrayRemove" => Some(Self::ArrayRemove), diff --git a/datafusion/proto/src/logical_plan/from_proto.rs b/datafusion/proto/src/logical_plan/from_proto.rs index e8c84ec12879..e2a1b219d09a 100644 --- a/datafusion/proto/src/logical_plan/from_proto.rs +++ b/datafusion/proto/src/logical_plan/from_proto.rs @@ -49,9 +49,9 @@ use datafusion_expr::window_frame::{check_window_frame, regularize_window_order_ use datafusion_expr::{ acosh, array_element, array_except, array_intersect, array_pop_back, array_pop_front, array_position, array_positions, array_remove, array_remove_all, array_remove_n, - array_repeat, array_replace, array_replace_all, array_replace_n, array_resize, - array_slice, array_union, ascii, asinh, atan, atan2, atanh, bit_length, btrim, cbrt, - ceil, character_length, chr, coalesce, concat_expr, concat_ws_expr, cos, cosh, cot, + array_replace, array_replace_all, array_replace_n, array_resize, array_slice, + array_union, ascii, asinh, atan, atan2, atanh, bit_length, btrim, cbrt, ceil, + character_length, chr, coalesce, concat_expr, concat_ws_expr, cos, cosh, cot, current_date, current_time, degrees, digest, ends_with, exp, expr::{self, InList, Sort, WindowFunction}, factorial, find_in_set, floor, from_unixtime, gcd, initcap, iszero, lcm, left, @@ -478,7 +478,6 @@ impl From<&protobuf::ScalarFunction> for BuiltinScalarFunction { ScalarFunction::ArrayPopBack => Self::ArrayPopBack, ScalarFunction::ArrayPosition => Self::ArrayPosition, ScalarFunction::ArrayPositions => Self::ArrayPositions, - ScalarFunction::ArrayRepeat => Self::ArrayRepeat, ScalarFunction::ArrayRemove => Self::ArrayRemove, ScalarFunction::ArrayRemoveN => Self::ArrayRemoveN, ScalarFunction::ArrayRemoveAll => Self::ArrayRemoveAll, @@ -1418,10 +1417,6 @@ pub fn parse_expr( parse_expr(&args[0], registry, codec)?, parse_expr(&args[1], registry, codec)?, )), - ScalarFunction::ArrayRepeat => Ok(array_repeat( - parse_expr(&args[0], registry, codec)?, - parse_expr(&args[1], registry, codec)?, - )), ScalarFunction::ArrayRemove => Ok(array_remove( parse_expr(&args[0], registry, codec)?, parse_expr(&args[1], registry, codec)?, diff --git a/datafusion/proto/src/logical_plan/to_proto.rs b/datafusion/proto/src/logical_plan/to_proto.rs index c25e2e1ecd22..b89e89570d89 100644 --- a/datafusion/proto/src/logical_plan/to_proto.rs +++ b/datafusion/proto/src/logical_plan/to_proto.rs @@ -1460,7 +1460,6 @@ impl TryFrom<&BuiltinScalarFunction> for protobuf::ScalarFunction { BuiltinScalarFunction::ArrayPopBack => Self::ArrayPopBack, BuiltinScalarFunction::ArrayPosition => Self::ArrayPosition, BuiltinScalarFunction::ArrayPositions => Self::ArrayPositions, - BuiltinScalarFunction::ArrayRepeat => Self::ArrayRepeat, BuiltinScalarFunction::ArrayResize => Self::ArrayResize, BuiltinScalarFunction::ArrayRemove => Self::ArrayRemove, BuiltinScalarFunction::ArrayRemoveN => Self::ArrayRemoveN, diff --git a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs index dff56b900fd4..2c8cf07e9eff 100644 --- a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs +++ b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs @@ -558,6 +558,7 @@ async fn roundtrip_expr_api() -> Result<()> { ), array_empty(make_array(vec![lit(1), lit(2), lit(3)])), array_length(make_array(vec![lit(1), lit(2), lit(3)])), + array_repeat(lit(1), lit(3)), flatten(make_array(vec![lit(1), lit(2), lit(3)])), array_sort( make_array(vec![lit(3), lit(4), lit(1), lit(2)]),