You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by co...@apache.org on 2026/04/17 16:32:37 UTC
(datafusion-comet) branch main updated: feat: support sort_array expression (#3706)
This is an automated email from the ASF dual-hosted git repository.
comphead pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-comet.git
The following commit(s) were added to refs/heads/main by this push:
new 915d5bdb5 feat: support sort_array expression (#3706)
915d5bdb5 is described below
commit 915d5bdb5e3a4f998e4a59589c31f4218bb47e74
Author: Han-Wen Tsao <g9...@yahoo.com>
AuthorDate: Sat Apr 18 00:32:32 2026 +0800
feat: support sort_array expression (#3706)
---
docs/source/user-guide/latest/compatibility.md | 1 +
docs/spark_expressions_support.md | 2 +-
.../org/apache/comet/serde/QueryPlanSerde.scala | 34 +-
.../main/scala/org/apache/comet/serde/arrays.scala | 77 +++-
.../sql-tests/expressions/array/sort_array.sql | 401 +++++++++++++++++++++
5 files changed, 493 insertions(+), 22 deletions(-)
diff --git a/docs/source/user-guide/latest/compatibility.md b/docs/source/user-guide/latest/compatibility.md
index 6625a495f..b12ebfed4 100644
--- a/docs/source/user-guide/latest/compatibility.md
+++ b/docs/source/user-guide/latest/compatibility.md
@@ -66,6 +66,7 @@ the [Comet Supported Expressions Guide](expressions.md) for more information on
- **ArrayUnion**: Sorts input arrays before performing the union, while Spark preserves the order of the first array
and appends unique elements from the second.
[#3644](https://github.com/apache/datafusion-comet/issues/3644)
+- **SortArray**: Nested arrays with `Struct` or `Null` child values are not supported natively and will fall back to Spark.
### Date/Time Expressions
diff --git a/docs/spark_expressions_support.md b/docs/spark_expressions_support.md
index 420778375..9d9e8f701 100644
--- a/docs/spark_expressions_support.md
+++ b/docs/spark_expressions_support.md
@@ -105,7 +105,7 @@
- [ ] sequence
- [ ] shuffle
- [ ] slice
-- [ ] sort_array
+- [x] sort_array
### bitwise_funcs
diff --git a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
index b8278cce9..810d9bd7d 100644
--- a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
@@ -60,6 +60,7 @@ object QueryPlanSerde extends Logging with CometExprShim {
classOf[ArrayMin] -> CometArrayMin,
classOf[ArrayRemove] -> CometArrayRemove,
classOf[ArrayRepeat] -> CometArrayRepeat,
+ classOf[SortArray] -> CometSortArray,
classOf[ArraysOverlap] -> CometArraysOverlap,
classOf[ArrayUnion] -> CometArrayUnion,
classOf[CreateArray] -> CometCreateArray,
@@ -796,30 +797,23 @@ object QueryPlanSerde extends Logging with CometExprShim {
* TODO: Include SparkSQL's [[YearMonthIntervalType]] and [[DayTimeIntervalType]]
*/
// scalastyle:on
- def supportedSortType(op: SparkPlan, sortOrder: Seq[SortOrder]): Boolean = {
- def canRank(dt: DataType): Boolean = {
- dt match {
- case _: ByteType | _: ShortType | _: IntegerType | _: LongType | _: FloatType |
- _: DoubleType | _: DecimalType =>
- true
- case _: DateType | _: TimestampType | _: TimestampNTZType =>
- true
- case _: BooleanType | _: BinaryType | _: StringType => true
- case _ => false
- }
+ def supportedScalarSortElementType(dt: DataType): Boolean = {
+ dt match {
+ case _: ByteType | _: ShortType | _: IntegerType | _: LongType | _: FloatType |
+ _: DoubleType | _: DecimalType | _: DateType | _: TimestampType | _: TimestampNTZType |
+ _: BooleanType | _: BinaryType | _: StringType =>
+ true
+ case _ =>
+ false
}
+ }
+ def supportedSortType(op: SparkPlan, sortOrder: Seq[SortOrder]): Boolean = {
if (sortOrder.length == 1) {
val canSort = sortOrder.head.dataType match {
- case _: ByteType | _: ShortType | _: IntegerType | _: LongType | _: FloatType |
- _: DoubleType | _: DecimalType =>
- true
- case _: DateType | _: TimestampType | _: TimestampNTZType =>
- true
- case _: BooleanType | _: BinaryType | _: StringType => true
- case ArrayType(elementType, _) => canRank(elementType)
- case MapType(_, valueType, _) => canRank(valueType)
- case _ => false
+ case ArrayType(elementType, _) => supportedScalarSortElementType(elementType)
+ case MapType(_, valueType, _) => supportedScalarSortElementType(valueType)
+ case _ => supportedScalarSortElementType(sortOrder.head.dataType)
}
if (!canSort) {
withInfo(op, s"Sort on single column of type ${sortOrder.head.dataType} is not supported")
diff --git a/spark/src/main/scala/org/apache/comet/serde/arrays.scala b/spark/src/main/scala/org/apache/comet/serde/arrays.scala
index f107d5b30..e05967958 100644
--- a/spark/src/main/scala/org/apache/comet/serde/arrays.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/arrays.scala
@@ -21,11 +21,12 @@ package org.apache.comet.serde
import scala.annotation.tailrec
-import org.apache.spark.sql.catalyst.expressions.{ArrayAppend, ArrayContains, ArrayDistinct, ArrayExcept, ArrayFilter, ArrayInsert, ArrayIntersect, ArrayJoin, ArrayMax, ArrayMin, ArrayRemove, ArrayRepeat, ArraysOverlap, ArrayUnion, Attribute, CreateArray, ElementAt, Expression, Flatten, GetArrayItem, IsNotNull, Literal, Reverse, Size}
+import org.apache.spark.sql.catalyst.expressions.{ArrayAppend, ArrayContains, ArrayDistinct, ArrayExcept, ArrayFilter, ArrayInsert, ArrayIntersect, ArrayJoin, ArrayMax, ArrayMin, ArrayRemove, ArrayRepeat, ArraysOverlap, ArrayUnion, Attribute, CreateArray, ElementAt, Expression, Flatten, GetArrayItem, IsNotNull, Literal, Reverse, Size, SortArray}
import org.apache.spark.sql.catalyst.util.GenericArrayData
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.types._
+import org.apache.comet.CometConf
import org.apache.comet.CometSparkSessionExtensions.withInfo
import org.apache.comet.serde.QueryPlanSerde._
import org.apache.comet.shims.CometExprShim
@@ -136,6 +137,80 @@ object CometArrayDistinct extends CometExpressionSerde[ArrayDistinct] {
}
}
+object CometSortArray extends CometExpressionSerde[SortArray] {
+ private def containsFloatingPoint(dt: DataType): Boolean = {
+ dt match {
+ case FloatType | DoubleType => true
+ case ArrayType(elementType, _) => containsFloatingPoint(elementType)
+ case StructType(fields) => fields.exists(f => containsFloatingPoint(f.dataType))
+ case MapType(keyType, valueType, _) =>
+ containsFloatingPoint(keyType) || containsFloatingPoint(valueType)
+ case _ => false
+ }
+ }
+
+ private def supportedSortArrayElementType(
+ dt: DataType,
+ nestedInArray: Boolean = false): Boolean = {
+ dt match {
+ // DataFusion's array_sort compares nested arrays through Arrow's rank kernel.
+ // That kernel does not support Struct or Null child values,
+ // so array<array<struct<...>>> and array<array<null>> would fail at runtime.
+ case _: NullType if !nestedInArray =>
+ true
+ case ArrayType(elementType, _) =>
+ supportedSortArrayElementType(elementType, nestedInArray = true)
+ case StructType(fields) if !nestedInArray =>
+ fields.forall(f => supportedSortArrayElementType(f.dataType))
+ case _ =>
+ supportedScalarSortElementType(dt)
+ }
+ }
+
+ override def getSupportLevel(expr: SortArray): SupportLevel = {
+ val elementType = expr.base.dataType.asInstanceOf[ArrayType].elementType
+
+ if (!supportedSortArrayElementType(elementType)) {
+ Unsupported(Some(s"Sort on array element type $elementType is not supported"))
+ } else if (CometConf.COMET_EXEC_STRICT_FLOATING_POINT.get() &&
+ containsFloatingPoint(elementType)) {
+ Incompatible(
+ Some(
+ "Sorting on floating-point is not 100% compatible with Spark, and Comet is running " +
+ s"with ${CometConf.COMET_EXEC_STRICT_FLOATING_POINT.key}=true. " +
+ s"${CometConf.COMPAT_GUIDE}"))
+ } else {
+ Compatible()
+ }
+ }
+
+ override def convert(
+ expr: SortArray,
+ inputs: Seq[Attribute],
+ binding: Boolean): Option[ExprOuterClass.Expr] = {
+ val arrayExprProto = exprToProtoInternal(expr.base, inputs, binding)
+ val (sortDirectionExprProto, nullOrderingExprProto) = expr.ascendingOrder match {
+ case Literal(value: Boolean, BooleanType) =>
+ val direction = if (value) "ASC" else "DESC"
+ val nullOrdering = if (value) "NULLS FIRST" else "NULLS LAST"
+ (
+ exprToProtoInternal(Literal(direction), inputs, binding),
+ exprToProtoInternal(Literal(nullOrdering), inputs, binding))
+ case other =>
+ withInfo(expr, s"ascendingOrder must be a boolean literal: $other")
+ (None, None)
+ }
+
+ val sortArrayScalarExpr =
+ scalarFunctionExprToProto(
+ "array_sort",
+ arrayExprProto,
+ sortDirectionExprProto,
+ nullOrderingExprProto)
+ optExprWithInfo(sortArrayScalarExpr, expr, expr.children: _*)
+ }
+}
+
object CometArrayIntersect extends CometExpressionSerde[ArrayIntersect] {
override def getSupportLevel(expr: ArrayIntersect): SupportLevel = Incompatible(None)
diff --git a/spark/src/test/resources/sql-tests/expressions/array/sort_array.sql b/spark/src/test/resources/sql-tests/expressions/array/sort_array.sql
new file mode 100644
index 000000000..1ced53394
--- /dev/null
+++ b/spark/src/test/resources/sql-tests/expressions/array/sort_array.sql
@@ -0,0 +1,401 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- ConfigMatrix: parquet.enable.dictionary=false,true
+
+statement
+CREATE TABLE test_sort_array_int(arr array<int>) USING parquet
+
+statement
+INSERT INTO test_sort_array_int VALUES
+ (array(3, 1, 4, 1, 5)),
+ (array(3, NULL, 1, NULL, 2)),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_int
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_int
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_int
+
+statement
+CREATE TABLE test_sort_array_string(arr array<string>) USING parquet
+
+statement
+INSERT INTO test_sort_array_string VALUES
+ (array('d', 'c', 'b', 'a')),
+ (array('b', NULL, 'a')),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_string
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_string
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_string
+
+statement
+CREATE TABLE test_sort_array_double(arr array<double>) USING parquet
+
+statement
+INSERT INTO test_sort_array_double VALUES
+ (array(
+ CAST('Infinity' AS DOUBLE),
+ CAST('-Infinity' AS DOUBLE),
+ CAST('NaN' AS DOUBLE),
+ 3.0,
+ 1.0,
+ NULL,
+ -0.0,
+ 0.0)),
+ (array(
+ CAST('NaN' AS DOUBLE),
+ CAST('NaN' AS DOUBLE),
+ CAST('Infinity' AS DOUBLE),
+ CAST('-Infinity' AS DOUBLE),
+ -5.0,
+ 2.0)),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_double
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_double
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_double
+
+statement
+CREATE TABLE test_sort_array_float(arr array<float>) USING parquet
+
+statement
+INSERT INTO test_sort_array_float VALUES
+ (array(
+ CAST('Infinity' AS FLOAT),
+ CAST('-Infinity' AS FLOAT),
+ CAST('NaN' AS FLOAT),
+ CAST(3.0 AS FLOAT),
+ CAST(1.0 AS FLOAT),
+ CAST(NULL AS FLOAT),
+ CAST(-0.0 AS FLOAT),
+ CAST(0.0 AS FLOAT))),
+ (array(
+ CAST('NaN' AS FLOAT),
+ CAST('Infinity' AS FLOAT),
+ CAST('-Infinity' AS FLOAT),
+ CAST(-5.0 AS FLOAT),
+ CAST(2.0 AS FLOAT))),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_float
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_float
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_float
+
+statement
+CREATE TABLE test_sort_array_decimal(arr array<decimal(12, 3)>) USING parquet
+
+statement
+INSERT INTO test_sort_array_decimal VALUES
+ (CAST(array(CAST(100 AS DECIMAL(10, 0)), CAST(10 AS DECIMAL(10, 0))) AS array<decimal(12, 3)>)),
+ (CAST(array(
+ CAST(1 AS DECIMAL(10, 0)),
+ CAST(1.0 AS DECIMAL(10, 1)),
+ CAST(1.00 AS DECIMAL(10, 2)),
+ CAST(1.000 AS DECIMAL(10, 3))) AS array<decimal(12, 3)>)),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_decimal
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_decimal
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_decimal
+
+statement
+CREATE TABLE test_sort_array_boolean(arr array<boolean>) USING parquet
+
+statement
+INSERT INTO test_sort_array_boolean VALUES
+ (array(true, false, true, false)),
+ (array(true, false, true, NULL, false)),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_boolean
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_boolean
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_boolean
+
+statement
+CREATE TABLE test_sort_array_date(arr array<date>) USING parquet
+
+statement
+INSERT INTO test_sort_array_date VALUES
+ (array(DATE '2026-01-03', DATE '2026-01-01', DATE '2026-01-02')),
+ (array(DATE '2026-01-02', NULL, DATE '2026-01-01')),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_date
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_date
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_date
+
+statement
+CREATE TABLE test_sort_array_timestamp(arr array<timestamp>) USING parquet
+
+statement
+INSERT INTO test_sort_array_timestamp VALUES
+ (array(
+ TIMESTAMP '2026-01-03 01:00:00',
+ TIMESTAMP '2026-01-01 02:00:00',
+ TIMESTAMP '2026-01-02 03:00:00')),
+ (array(
+ TIMESTAMP '2026-01-02 00:00:00',
+ NULL,
+ TIMESTAMP '2026-01-01 00:00:00')),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_timestamp
+
+query
+SELECT sort_array(arr, true) FROM test_sort_array_timestamp
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_timestamp
+
+statement
+CREATE TABLE test_sort_array_binary(arr array<binary>) USING parquet
+
+statement
+INSERT INTO test_sort_array_binary VALUES
+ (array(unhex('FF'), unhex('00'), unhex('0A'))),
+ (array(unhex('0B'), NULL, unhex('01'))),
+ (array()),
+ (NULL)
+
+query
+SELECT
+ hex(element_at(sorted_arr, 1)),
+ hex(element_at(sorted_arr, 2)),
+ hex(element_at(sorted_arr, 3))
+FROM (
+ SELECT sort_array(arr) AS sorted_arr
+ FROM test_sort_array_binary
+)
+
+query
+SELECT
+ hex(element_at(sorted_arr, 1)),
+ hex(element_at(sorted_arr, 2)),
+ hex(element_at(sorted_arr, 3))
+FROM (
+ SELECT sort_array(arr, true) AS sorted_arr
+ FROM test_sort_array_binary
+)
+
+query
+SELECT
+ hex(element_at(sorted_arr, 1)),
+ hex(element_at(sorted_arr, 2)),
+ hex(element_at(sorted_arr, 3))
+FROM (
+ SELECT sort_array(arr, false) AS sorted_arr
+ FROM test_sort_array_binary
+)
+
+statement
+CREATE TABLE test_sort_array_struct(arr array<struct<a:int,b:string>>) USING parquet
+
+statement
+INSERT INTO test_sort_array_struct VALUES
+ (array(
+ named_struct('a', 2, 'b', 'b'),
+ named_struct('a', 1, 'b', 'c'),
+ named_struct('a', 1, 'b', 'a'))),
+ (array(
+ named_struct('a', 2, 'b', NULL),
+ named_struct('a', 1, 'b', 'z'),
+ named_struct('a', 1, 'b', NULL))),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_struct
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_struct
+
+statement
+CREATE TABLE test_sort_array_nested(arr array<array<int>>) USING parquet
+
+statement
+INSERT INTO test_sort_array_nested VALUES
+ (array(array(2, 3), array(1), array(2, 1))),
+ (array(array(1, NULL), array(1), NULL)),
+ (array()),
+ (NULL)
+
+query
+SELECT sort_array(arr) FROM test_sort_array_nested
+
+query
+SELECT sort_array(arr, false) FROM test_sort_array_nested
+
+statement
+CREATE TABLE test_sort_array_nested_struct(arr array<array<struct<a:int>>>) USING parquet
+
+statement
+INSERT INTO test_sort_array_nested_struct VALUES
+ (array(
+ array(named_struct('a', 2)),
+ array(named_struct('a', 1)))),
+ (array()),
+ (NULL)
+
+query expect_fallback(Sort on array element type ArrayType(StructType(StructField(a,IntegerType)
+SELECT sort_array(arr) FROM test_sort_array_nested_struct
+
+query expect_fallback(Sort on array element type ArrayType(StructType(StructField(a,IntegerType)
+SELECT sort_array(arr, false) FROM test_sort_array_nested_struct
+
+-- literal arguments
+query
+SELECT
+ sort_array(array(3, 1, 4, 1, 5)),
+ sort_array(array(3, 1, 4, 1, 5), true),
+ sort_array(array(3, NULL, 1, NULL, 2)),
+ sort_array(array(3, NULL, 1, NULL, 2), false),
+ sort_array(
+ array(
+ CAST('Infinity' AS DOUBLE),
+ CAST('-Infinity' AS DOUBLE),
+ CAST('NaN' AS DOUBLE),
+ 1.0,
+ NULL,
+ -0.0,
+ 0.0)),
+ sort_array(
+ array(
+ CAST('Infinity' AS DOUBLE),
+ CAST('-Infinity' AS DOUBLE),
+ CAST('NaN' AS DOUBLE),
+ 1.0,
+ NULL,
+ -0.0,
+ 0.0),
+ false),
+ sort_array(
+ array(
+ CAST('Infinity' AS FLOAT),
+ CAST('-Infinity' AS FLOAT),
+ CAST('NaN' AS FLOAT),
+ CAST(1.0 AS FLOAT),
+ CAST(NULL AS FLOAT),
+ CAST(-0.0 AS FLOAT),
+ CAST(0.0 AS FLOAT))),
+ sort_array(
+ array(
+ CAST('Infinity' AS FLOAT),
+ CAST('-Infinity' AS FLOAT),
+ CAST('NaN' AS FLOAT),
+ CAST(1.0 AS FLOAT),
+ CAST(NULL AS FLOAT),
+ CAST(-0.0 AS FLOAT),
+ CAST(0.0 AS FLOAT)),
+ false),
+ sort_array(
+ CAST(array(
+ CAST(100 AS DECIMAL(10, 0)),
+ CAST(10 AS DECIMAL(10, 0)),
+ CAST(1 AS DECIMAL(10, 0)),
+ CAST(1.00 AS DECIMAL(10, 2))) AS array<decimal(12, 3)>)),
+ sort_array(
+ CAST(array(
+ CAST(100 AS DECIMAL(10, 0)),
+ CAST(10 AS DECIMAL(10, 0)),
+ CAST(1 AS DECIMAL(10, 0)),
+ CAST(1.00 AS DECIMAL(10, 2))) AS array<decimal(12, 3)>),
+ false),
+ sort_array(array(true, false, true, false)),
+ sort_array(array(true, false, true, NULL, false)),
+ sort_array(array(true, false, true, NULL, false), false),
+ sort_array(array(DATE '2026-01-03', DATE '2026-01-01', DATE '2026-01-02')),
+ sort_array(array(DATE '2026-01-02', NULL, DATE '2026-01-01'), false),
+ sort_array(
+ array(
+ TIMESTAMP '2026-01-03 01:00:00',
+ TIMESTAMP '2026-01-01 02:00:00',
+ TIMESTAMP '2026-01-02 03:00:00')),
+ sort_array(
+ array(
+ TIMESTAMP '2026-01-02 00:00:00',
+ NULL,
+ TIMESTAMP '2026-01-01 00:00:00'),
+ false),
+ hex(element_at(sort_array(array(unhex('FF'), unhex('00'), unhex('0A'))), 1)),
+ hex(element_at(sort_array(array(unhex('FF'), unhex('00'), unhex('0A'))), 2)),
+ hex(element_at(sort_array(array(unhex('FF'), unhex('00'), unhex('0A'))), 3)),
+ hex(element_at(sort_array(array(unhex('0B'), NULL, unhex('01')), false), 1)),
+ hex(element_at(sort_array(array(unhex('0B'), NULL, unhex('01')), false), 2)),
+ hex(element_at(sort_array(array(unhex('0B'), NULL, unhex('01')), false), 3)),
+ sort_array(
+ array(
+ named_struct('a', 2, 'b', 'b'),
+ named_struct('a', 1, 'b', 'c'),
+ named_struct('a', 1, 'b', 'a'))),
+ sort_array(array(array(2, 3), array(1), array(2, 1))),
+ sort_array(array(array(1, NULL), array(1), NULL)),
+ sort_array(array(NULL, NULL)),
+ sort_array(cast(NULL as array<int>))
+
+query expect_fallback(Sort on array element type ArrayType(StructType(StructField(a,IntegerType)
+SELECT sort_array(
+ array(
+ array(named_struct('a', 2)),
+ array(named_struct('a', 1))))
+
+query expect_error(BOOLEAN)
+SELECT sort_array(array(3, 1, 4, 1, 5), 1)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org