Skip to content

Commit 23845c8

Browse files
committed
Rename array() function to make_array(), extend array[]
1 parent 85f7fc9 commit 23845c8

11 files changed

Lines changed: 183 additions & 164 deletions

File tree

datafusion/core/src/logical_plan/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ pub use datafusion_common::{
2727
Column, DFField, DFSchema, DFSchemaRef, ExprSchema, ToDFSchema,
2828
};
2929
pub use datafusion_expr::{
30-
abs, acos, and, approx_distinct, approx_percentile_cont, array, ascii, asin, atan,
31-
atan2, avg, bit_length, btrim, call_fn, case, cast, ceil, character_length, chr,
32-
coalesce, col, combine_filters, concat, concat_expr, concat_ws, concat_ws_expr, cos,
33-
count, count_distinct, create_udaf, create_udf, date_part, date_trunc, digest,
34-
exists, exp, expr_rewriter,
30+
abs, acos, and, approx_distinct, approx_percentile_cont, ascii, asin, atan, atan2,
31+
avg, bit_length, btrim, call_fn, case, cast, ceil, character_length, chr, coalesce,
32+
col, combine_filters, concat, concat_expr, concat_ws, concat_ws_expr, cos, count,
33+
count_distinct, create_udaf, create_udf, date_part, date_trunc, digest, exists, exp,
34+
expr_rewriter,
3535
expr_rewriter::{
3636
normalize_col, normalize_col_with_schemas, normalize_cols, replace_col,
3737
rewrite_sort_cols_by_aggs, unnormalize_col, unnormalize_cols, ExprRewritable,
@@ -50,11 +50,11 @@ pub use datafusion_expr::{
5050
StringifiedPlan, Subquery, TableScan, ToStringifiedPlan, Union,
5151
UserDefinedLogicalNode, Values,
5252
},
53-
lower, lpad, ltrim, max, md5, min, not_exists, not_in_subquery, now, now_expr,
54-
nullif, octet_length, or, power, random, regexp_match, regexp_replace, repeat,
55-
replace, reverse, right, round, rpad, rtrim, scalar_subquery, sha224, sha256, sha384,
56-
sha512, signum, sin, split_part, sqrt, starts_with, strpos, substr, sum, tan, to_hex,
57-
to_timestamp_micros, to_timestamp_millis, to_timestamp_seconds, translate, trim,
58-
trunc, unalias, upper, when, Expr, ExprSchemable, Literal, Operator,
53+
lower, lpad, ltrim, make_array, max, md5, min, not_exists, not_in_subquery, now,
54+
now_expr, nullif, octet_length, or, power, random, regexp_match, regexp_replace,
55+
repeat, replace, reverse, right, round, rpad, rtrim, scalar_subquery, sha224, sha256,
56+
sha384, sha512, signum, sin, split_part, sqrt, starts_with, strpos, substr, sum, tan,
57+
to_hex, to_timestamp_micros, to_timestamp_millis, to_timestamp_seconds, translate,
58+
trim, trunc, unalias, upper, when, Expr, ExprSchemable, Literal, Operator,
5959
};
6060
pub use datafusion_optimizer::expr_simplifier::{ExprSimplifiable, SimplifyInfo};

datafusion/core/src/prelude.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ pub use crate::execution::options::{
3131
AvroReadOptions, CsvReadOptions, NdJsonReadOptions, ParquetReadOptions,
3232
};
3333
pub use crate::logical_plan::{
34-
approx_percentile_cont, array, ascii, avg, bit_length, btrim, cast, character_length,
35-
chr, coalesce, col, concat, concat_ws, count, create_udf, date_part, date_trunc,
36-
digest, exists, from_unixtime, in_list, in_subquery, initcap, left, length, lit,
37-
lower, lpad, ltrim, max, md5, min, not_exists, not_in_subquery, now, octet_length,
34+
approx_percentile_cont, ascii, avg, bit_length, btrim, cast, character_length, chr,
35+
coalesce, col, concat, concat_ws, count, create_udf, date_part, date_trunc, digest,
36+
exists, from_unixtime, in_list, in_subquery, initcap, left, length, lit, lower, lpad,
37+
ltrim, make_array, max, md5, min, not_exists, not_in_subquery, now, octet_length,
3838
random, regexp_match, regexp_replace, repeat, replace, reverse, right, rpad, rtrim,
3939
scalar_subquery, sha224, sha256, sha384, sha512, split_part, starts_with, strpos,
4040
substr, sum, to_hex, translate, trim, upper, Column, Expr, JoinType, Partitioning,

datafusion/core/tests/sql/functions.rs

Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ async fn query_concat() -> Result<()> {
111111
Ok(())
112112
}
113113

114-
#[tokio::test]
115-
async fn query_array() -> Result<()> {
114+
// Return a session context with table "test" registered with 2 columns
115+
fn array_context() -> SessionContext {
116116
let schema = Arc::new(Schema::new(vec![
117117
Field::new("c1", DataType::Utf8, false),
118118
Field::new("c2", DataType::Int32, true),
@@ -124,43 +124,110 @@ async fn query_array() -> Result<()> {
124124
Arc::new(StringArray::from_slice(&["", "a", "aa", "aaa"])),
125125
Arc::new(Int32Array::from(vec![Some(0), Some(1), None, Some(3)])),
126126
],
127-
)?;
127+
)
128+
.unwrap();
128129

129-
let table = MemTable::try_new(schema, vec![vec![data]])?;
130+
let table = MemTable::try_new(schema, vec![vec![data]]).unwrap();
130131

131132
let ctx = SessionContext::new();
132-
ctx.register_table("test", Arc::new(table))?;
133-
let sql = "SELECT array(c1, cast(c2 as varchar)) FROM test";
133+
ctx.register_table("test", Arc::new(table)).unwrap();
134+
ctx
135+
}
136+
137+
#[tokio::test]
138+
async fn query_array() {
139+
let ctx = array_context();
140+
let sql = "SELECT array[c1, cast(c2 as varchar)] FROM test";
134141
let actual = execute_to_batches(&ctx, sql).await;
135142
let expected = vec![
136-
"+--------------------------------------+",
137-
"| array(test.c1,CAST(test.c2 AS Utf8)) |",
138-
"+--------------------------------------+",
139-
"| [, 0] |",
140-
"| [a, 1] |",
141-
"| [aa, ] |",
142-
"| [aaa, 3] |",
143-
"+--------------------------------------+",
143+
"+----------+",
144+
"| array |",
145+
"+----------+",
146+
"| [, 0] |",
147+
"| [a, 1] |",
148+
"| [aa, ] |",
149+
"| [aaa, 3] |",
150+
"+----------+",
151+
];
152+
assert_batches_eq!(expected, &actual);
153+
}
154+
155+
#[tokio::test]
156+
async fn query_make_array() {
157+
let ctx = array_context();
158+
let sql = "SELECT make_array(c1, cast(c2 as varchar)) FROM test";
159+
let actual = execute_to_batches(&ctx, sql).await;
160+
let expected = vec![
161+
"+------------------------------------------+",
162+
"| makearray(test.c1,CAST(test.c2 AS Utf8)) |",
163+
"+------------------------------------------+",
164+
"| [, 0] |",
165+
"| [a, 1] |",
166+
"| [aa, ] |",
167+
"| [aaa, 3] |",
168+
"+------------------------------------------+",
144169
];
145170
assert_batches_eq!(expected, &actual);
146-
Ok(())
147171
}
148172

149173
#[tokio::test]
150-
async fn query_array_scalar() -> Result<()> {
174+
async fn query_array_scalar() {
151175
let ctx = SessionContext::new();
152176

153-
let sql = "SELECT array(1, 2, 3);";
177+
let sql = "SELECT array[1, 2, 3];";
154178
let actual = execute_to_batches(&ctx, sql).await;
155179
let expected = vec![
156-
"+-----------------------------------+",
157-
"| array(Int64(1),Int64(2),Int64(3)) |",
158-
"+-----------------------------------+",
159-
"| [1, 2, 3] |",
160-
"+-----------------------------------+",
180+
"+-----------+",
181+
"| array |",
182+
"+-----------+",
183+
"| [1, 2, 3] |",
184+
"+-----------+",
185+
];
186+
assert_batches_eq!(expected, &actual);
187+
188+
// alternate syntax format
189+
let sql = "SELECT [1, 2, 3];";
190+
let actual = execute_to_batches(&ctx, sql).await;
191+
assert_batches_eq!(expected, &actual);
192+
}
193+
194+
#[tokio::test]
195+
async fn query_array_scalar_bad_types() {
196+
let ctx = SessionContext::new();
197+
198+
// no common type to coerce to, should error
199+
let err = plan_and_collect(&ctx, "SELECT [1, true, null]")
200+
.await
201+
.unwrap_err();
202+
assert_eq!(err.to_string(), "Error during planning: Coercion from [Int64, Boolean, Null] to the signature VariadicEqual failed.",);
203+
}
204+
205+
#[tokio::test]
206+
async fn query_array_scalar_coerce() {
207+
let ctx = SessionContext::new();
208+
209+
// The planner should be able to coerce this to all integers
210+
// https://github.com/apache/arrow-datafusion/issues/3170
211+
let err = plan_and_collect(&ctx, "SELECT [1, 2, '3']")
212+
.await
213+
.unwrap_err();
214+
assert_eq!(err.to_string(), "Error during planning: Coercion from [Int64, Int64, Utf8] to the signature VariadicEqual failed.",);
215+
}
216+
217+
#[tokio::test]
218+
async fn query_make_array_scalar() {
219+
let ctx = SessionContext::new();
220+
221+
let sql = "SELECT make_array(1, 2, 3);";
222+
let actual = execute_to_batches(&ctx, sql).await;
223+
let expected = vec![
224+
"+---------------------------------------+",
225+
"| makearray(Int64(1),Int64(2),Int64(3)) |",
226+
"+---------------------------------------+",
227+
"| [1, 2, 3] |",
228+
"+---------------------------------------+",
161229
];
162230
assert_batches_eq!(expected, &actual);
163-
Ok(())
164231
}
165232

166233
#[tokio::test]

datafusion/expr/src/built_in_function.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ pub enum BuiltinScalarFunction {
7171
/// trunc
7272
Trunc,
7373

74-
// string functions
74+
// array functions
7575
/// construct an array from columns
76-
Array,
76+
MakeArray,
77+
78+
// string functions
7779
/// ascii
7880
Ascii,
7981
/// bit_length
@@ -204,7 +206,7 @@ impl BuiltinScalarFunction {
204206
BuiltinScalarFunction::Sqrt => Volatility::Immutable,
205207
BuiltinScalarFunction::Tan => Volatility::Immutable,
206208
BuiltinScalarFunction::Trunc => Volatility::Immutable,
207-
BuiltinScalarFunction::Array => Volatility::Immutable,
209+
BuiltinScalarFunction::MakeArray => Volatility::Immutable,
208210
BuiltinScalarFunction::Ascii => Volatility::Immutable,
209211
BuiltinScalarFunction::BitLength => Volatility::Immutable,
210212
BuiltinScalarFunction::Btrim => Volatility::Immutable,
@@ -297,8 +299,10 @@ impl FromStr for BuiltinScalarFunction {
297299
// conditional functions
298300
"coalesce" => BuiltinScalarFunction::Coalesce,
299301

302+
// array functions
303+
"make_array" => BuiltinScalarFunction::MakeArray,
304+
300305
// string functions
301-
"array" => BuiltinScalarFunction::Array,
302306
"ascii" => BuiltinScalarFunction::Ascii,
303307
"bit_length" => BuiltinScalarFunction::BitLength,
304308
"btrim" => BuiltinScalarFunction::Btrim,

datafusion/expr/src/expr_fn.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,9 @@ scalar_expr!(FromUnixtime, from_unixtime, unixtime);
382382
unary_scalar_expr!(ArrowTypeof, arrow_typeof, "data type");
383383

384384
/// Returns an array of fixed size with each argument on it.
385-
pub fn array(args: Vec<Expr>) -> Expr {
385+
pub fn make_array(args: Vec<Expr>) -> Expr {
386386
Expr::ScalarFunction {
387-
fun: built_in_function::BuiltinScalarFunction::Array,
387+
fun: built_in_function::BuiltinScalarFunction::MakeArray,
388388
args,
389389
}
390390
}

datafusion/expr/src/function.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use crate::nullif::SUPPORTED_NULLIF_TYPES;
2121
use crate::type_coercion::data_types;
2222
use crate::ColumnarValue;
2323
use crate::{
24-
array_expressions, conditional_expressions, struct_expressions, Accumulator,
25-
BuiltinScalarFunction, Signature, TypeSignature,
24+
conditional_expressions, struct_expressions, Accumulator, BuiltinScalarFunction,
25+
Signature, TypeSignature,
2626
};
2727
use arrow::datatypes::{DataType, Field, IntervalUnit, TimeUnit};
2828
use datafusion_common::{DataFusionError, Result};
@@ -96,7 +96,7 @@ pub fn return_type(
9696
// the return type of the built in function.
9797
// Some built-in functions' return type depends on the incoming type.
9898
match fun {
99-
BuiltinScalarFunction::Array => Ok(DataType::FixedSizeList(
99+
BuiltinScalarFunction::MakeArray => Ok(DataType::FixedSizeList(
100100
Box::new(Field::new("item", input_expr_types[0].clone(), true)),
101101
input_expr_types.len() as i32,
102102
)),
@@ -267,12 +267,8 @@ pub fn return_type(
267267
pub fn signature(fun: &BuiltinScalarFunction) -> Signature {
268268
// note: the physical expression must accept the type returned by this function or the execution panics.
269269

270-
// for now, the list is small, as we do not have many built-in functions.
271270
match fun {
272-
BuiltinScalarFunction::Array => Signature::variadic(
273-
array_expressions::SUPPORTED_ARRAY_TYPES.to_vec(),
274-
fun.volatility(),
275-
),
271+
BuiltinScalarFunction::MakeArray => Signature::variadic_equal(fun.volatility()),
276272
BuiltinScalarFunction::Struct => Signature::variadic(
277273
struct_expressions::SUPPORTED_STRUCT_TYPES.to_vec(),
278274
fun.volatility(),

datafusion/physical-expr/src/array_expressions.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ macro_rules! downcast_vec {
3434
}};
3535
}
3636

37-
macro_rules! array {
37+
/// Create an array of FixedSizeList from a set of individual Arrays
38+
/// where each element in the output FixedSizeList is the result of
39+
/// concatenating the corresponding values in the input Arrays
40+
macro_rules! make_fixed_size_list {
3841
($ARGS:expr, $ARRAY_TYPE:ident, $BUILDER_TYPE:ident) => {{
3942
// downcast all arguments to their common format
4043
let args =
@@ -59,7 +62,7 @@ macro_rules! array {
5962
}};
6063
}
6164

62-
fn array_array(args: &[ArrayRef]) -> Result<ArrayRef> {
65+
fn arrays_to_fixed_size_list_array(args: &[ArrayRef]) -> Result<ArrayRef> {
6366
// do not accept 0 arguments.
6467
if args.is_empty() {
6568
return Err(DataFusionError::Internal(
@@ -68,19 +71,21 @@ fn array_array(args: &[ArrayRef]) -> Result<ArrayRef> {
6871
}
6972

7073
let res = match args[0].data_type() {
71-
DataType::Utf8 => array!(args, StringArray, StringBuilder),
72-
DataType::LargeUtf8 => array!(args, LargeStringArray, LargeStringBuilder),
73-
DataType::Boolean => array!(args, BooleanArray, BooleanBuilder),
74-
DataType::Float32 => array!(args, Float32Array, Float32Builder),
75-
DataType::Float64 => array!(args, Float64Array, Float64Builder),
76-
DataType::Int8 => array!(args, Int8Array, Int8Builder),
77-
DataType::Int16 => array!(args, Int16Array, Int16Builder),
78-
DataType::Int32 => array!(args, Int32Array, Int32Builder),
79-
DataType::Int64 => array!(args, Int64Array, Int64Builder),
80-
DataType::UInt8 => array!(args, UInt8Array, UInt8Builder),
81-
DataType::UInt16 => array!(args, UInt16Array, UInt16Builder),
82-
DataType::UInt32 => array!(args, UInt32Array, UInt32Builder),
83-
DataType::UInt64 => array!(args, UInt64Array, UInt64Builder),
74+
DataType::Utf8 => make_fixed_size_list!(args, StringArray, StringBuilder),
75+
DataType::LargeUtf8 => {
76+
make_fixed_size_list!(args, LargeStringArray, LargeStringBuilder)
77+
}
78+
DataType::Boolean => make_fixed_size_list!(args, BooleanArray, BooleanBuilder),
79+
DataType::Float32 => make_fixed_size_list!(args, Float32Array, Float32Builder),
80+
DataType::Float64 => make_fixed_size_list!(args, Float64Array, Float64Builder),
81+
DataType::Int8 => make_fixed_size_list!(args, Int8Array, Int8Builder),
82+
DataType::Int16 => make_fixed_size_list!(args, Int16Array, Int16Builder),
83+
DataType::Int32 => make_fixed_size_list!(args, Int32Array, Int32Builder),
84+
DataType::Int64 => make_fixed_size_list!(args, Int64Array, Int64Builder),
85+
DataType::UInt8 => make_fixed_size_list!(args, UInt8Array, UInt8Builder),
86+
DataType::UInt16 => make_fixed_size_list!(args, UInt16Array, UInt16Builder),
87+
DataType::UInt32 => make_fixed_size_list!(args, UInt32Array, UInt32Builder),
88+
DataType::UInt64 => make_fixed_size_list!(args, UInt64Array, UInt64Builder),
8489
data_type => {
8590
return Err(DataFusionError::NotImplemented(format!(
8691
"Array is not implemented for type '{:?}'.",
@@ -92,13 +97,15 @@ fn array_array(args: &[ArrayRef]) -> Result<ArrayRef> {
9297
}
9398

9499
/// put values in an array.
95-
pub fn array(values: &[ColumnarValue]) -> Result<ColumnarValue> {
100+
pub fn make_array(values: &[ColumnarValue]) -> Result<ColumnarValue> {
96101
let arrays: Vec<ArrayRef> = values
97102
.iter()
98103
.map(|x| match x {
99104
ColumnarValue::Array(array) => array.clone(),
100105
ColumnarValue::Scalar(scalar) => scalar.to_array().clone(),
101106
})
102107
.collect();
103-
Ok(ColumnarValue::Array(array_array(arrays.as_slice())?))
108+
Ok(ColumnarValue::Array(arrays_to_fixed_size_list_array(
109+
arrays.as_slice(),
110+
)?))
104111
}

0 commit comments

Comments
 (0)