This is an automated email from the ASF dual-hosted git repository.
philo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-gluten.git
The following commit(s) were added to refs/heads/main by this push:
new 699c2f7a9f [GLUTEN-9392][VL] Support casting array element to varchar
(#9394)
699c2f7a9f is described below
commit 699c2f7a9fe5173a7a10d025168ed1a23a2f36f6
Author: Arnav Balyan <[email protected]>
AuthorDate: Mon Apr 28 21:06:44 2025 +0530
[GLUTEN-9392][VL] Support casting array element to varchar (#9394)
---
.../substrait/SubstraitToVeloxPlanValidator.cc | 27 ++++++++++
.../utils/clickhouse/ClickHouseTestSettings.scala | 5 ++
.../sql/catalyst/expressions/GlutenCastSuite.scala | 63 ++++++++++++++++++++++
.../utils/clickhouse/ClickHouseTestSettings.scala | 5 ++
.../sql/catalyst/expressions/GlutenCastSuite.scala | 63 ++++++++++++++++++++++
.../utils/clickhouse/ClickHouseTestSettings.scala | 5 ++
.../sql/catalyst/expressions/GlutenCastSuite.scala | 63 ++++++++++++++++++++++
.../utils/clickhouse/ClickHouseTestSettings.scala | 5 ++
.../sql/catalyst/expressions/GlutenCastSuite.scala | 63 ++++++++++++++++++++++
9 files changed, 299 insertions(+)
diff --git a/cpp/velox/substrait/SubstraitToVeloxPlanValidator.cc
b/cpp/velox/substrait/SubstraitToVeloxPlanValidator.cc
index 15b6949c78..a91c96f039 100644
--- a/cpp/velox/substrait/SubstraitToVeloxPlanValidator.cc
+++ b/cpp/velox/substrait/SubstraitToVeloxPlanValidator.cc
@@ -232,6 +232,22 @@ bool SubstraitToVeloxPlanValidator::validateScalarFunction(
return true;
}
+bool isSupportedArrayCast(const TypePtr& fromType, const TypePtr& toType) {
+ static const std::unordered_set<TypeKind> kAllowedArrayElementKinds = {
+ TypeKind::DOUBLE,
+ TypeKind::BOOLEAN,
+ TypeKind::TIMESTAMP,
+ };
+
+ // https://github.com/apache/incubator-gluten/issues/9392
+ // is currently WIP to add support for other types.
+ if (toType->isVarchar()) {
+ return kAllowedArrayElementKinds.count(fromType->kind()) > 0;
+ }
+
+ return false;
+}
+
bool SubstraitToVeloxPlanValidator::isAllowedCast(const TypePtr& fromType,
const TypePtr& toType) {
// Currently cast is not allowed for various categories, code has a bunch of
rules
// which define the cast categories and if we should offload to velox.
Currently,
@@ -275,6 +291,17 @@ bool SubstraitToVeloxPlanValidator::isAllowedCast(const
TypePtr& fromType, const
return false;
}
+ if (fromType->isArray() && toType->isArray()) {
+ const auto& toElem = toType->asArray().elementType();
+ const auto& fromElem = fromType->asArray().elementType();
+
+ if (!isAllowedCast(fromElem, toElem)) {
+ return false;
+ }
+
+ return isSupportedArrayCast(fromElem, toElem);
+ }
+
// Limited support for Complex types.
if (fromType->isArray() || fromType->isMap() || fromType->isRow()) {
return false;
diff --git
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index cdd2509680..ba21c3d6f4 100644
---
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -609,6 +609,11 @@ class ClickHouseTestSettings extends BackendTestSettings {
.exclude("SPARK-34727: cast from float II")
.exclude("SPARK-35720: cast invalid string input to timestamp without time
zone")
.exclude("Cast should output null for invalid strings when ANSI is not
enabled.")
+ .exclude("cast array element from integer to string")
+ .exclude("cast array element from double to string")
+ .exclude("cast array element from bool to string")
+ .exclude("cast array element from date to string")
+ .exclude("cast array from timestamp to string")
enableSuite[GlutenCastSuiteWithAnsiModeOn]
.exclude("null cast")
.exclude("cast string to date")
diff --git
a/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
index 31446aba08..235c761062 100644
---
a/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
+++
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
@@ -43,6 +43,69 @@ class GlutenCastSuite extends CastSuite with
GlutenTestsTrait {
UDTRegistration.register(classOf[IExampleBaseType].getName,
classOf[ExampleBaseTypeUDT].getName)
UDTRegistration.register(classOf[IExampleSubType].getName,
classOf[ExampleSubTypeUDT].getName)
+ test("cast array element from integer to string") {
+ val inputWithNull = Literal.create(Seq(1, null, 3), ArrayType(IntegerType))
+ val expectedWithNull = Seq("1", null, "3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Int], ArrayType(IntegerType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+
+ val inputNegative = Literal.create(Seq(-1, 0, 999999),
ArrayType(IntegerType))
+ val expectedNegative = Seq("-1", "0", "999999")
+ checkEvaluation(cast(inputNegative, ArrayType(StringType)),
expectedNegative)
+ }
+
+ test("cast array element from double to string") {
+ val inputWithNull = Literal.create(Seq(1.1, null, 3.3),
ArrayType(DoubleType))
+ val expectedWithNull = Seq("1.1", null, "3.3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputScientific = Literal.create(Seq(1.23e4, -5.67e-3),
ArrayType(DoubleType))
+ val expectedScientific = Seq("12300.0", "-0.00567")
+ checkEvaluation(cast(inputScientific, ArrayType(StringType)),
expectedScientific)
+ }
+
+ test("cast array element from bool to string") {
+ val inputWithNull = Literal.create(Seq(true, null, false),
ArrayType(BooleanType))
+ val expectedWithNull = Seq("true", null, "false")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Boolean], ArrayType(BooleanType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
+ test("cast array element from date to string") {
+ val inputWithNull = Literal.create(
+ Seq(Date.valueOf("2024-01-01"), null, Date.valueOf("2024-01-03")),
+ ArrayType(DateType)
+ )
+ val expectedWithNull = Seq("2024-01-01", null, "2024-01-03")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputLeapYear = Literal.create(
+ Seq(Date.valueOf("2020-02-29")),
+ ArrayType(DateType)
+ )
+ val expectedLeapYear = Seq("2020-02-29")
+ checkEvaluation(cast(inputLeapYear, ArrayType(StringType)),
expectedLeapYear)
+ }
+
+ test("cast array from timestamp to string") {
+ val inputWithNull = Literal.create(
+ Seq(Timestamp.valueOf("2023-01-01 12:00:00"), null,
Timestamp.valueOf("2023-12-31 23:59:59")),
+ ArrayType(TimestampType)
+ )
+ val expectedWithNull = Seq("2023-01-01 12:00:00", null, "2023-12-31
23:59:59")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Timestamp],
ArrayType(TimestampType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
testGluten("missing cases - from boolean") {
(DataTypeTestUtils.numericTypeWithoutDecimal + BooleanType).foreach {
t =>
diff --git
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index 2d9444e7a6..e095d7760a 100644
---
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -626,6 +626,11 @@ class ClickHouseTestSettings extends BackendTestSettings {
.exclude("SPARK-36924: Cast YearMonthIntervalType to IntegralType")
.exclude("SPARK-36924: Cast IntegralType to YearMonthIntervalType")
.exclude("Cast should output null for invalid strings when ANSI is not
enabled.")
+ .exclude("cast array element from integer to string")
+ .exclude("cast array element from double to string")
+ .exclude("cast array element from bool to string")
+ .exclude("cast array element from date to string")
+ .exclude("cast array from timestamp to string")
enableSuite[GlutenCastSuiteWithAnsiModeOn]
.exclude("null cast")
.exclude("cast string to date")
diff --git
a/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
index 2bc2f8b1a2..13eb8fa14c 100644
---
a/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
+++
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
@@ -43,6 +43,69 @@ class GlutenCastSuite extends CastSuite with
GlutenTestsTrait {
UDTRegistration.register(classOf[IExampleBaseType].getName,
classOf[ExampleBaseTypeUDT].getName)
UDTRegistration.register(classOf[IExampleSubType].getName,
classOf[ExampleSubTypeUDT].getName)
+ test("cast array element from integer to string") {
+ val inputWithNull = Literal.create(Seq(1, null, 3), ArrayType(IntegerType))
+ val expectedWithNull = Seq("1", null, "3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Int], ArrayType(IntegerType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+
+ val inputNegative = Literal.create(Seq(-1, 0, 999999),
ArrayType(IntegerType))
+ val expectedNegative = Seq("-1", "0", "999999")
+ checkEvaluation(cast(inputNegative, ArrayType(StringType)),
expectedNegative)
+ }
+
+ test("cast array element from double to string") {
+ val inputWithNull = Literal.create(Seq(1.1, null, 3.3),
ArrayType(DoubleType))
+ val expectedWithNull = Seq("1.1", null, "3.3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputScientific = Literal.create(Seq(1.23e4, -5.67e-3),
ArrayType(DoubleType))
+ val expectedScientific = Seq("12300.0", "-0.00567")
+ checkEvaluation(cast(inputScientific, ArrayType(StringType)),
expectedScientific)
+ }
+
+ test("cast array element from bool to string") {
+ val inputWithNull = Literal.create(Seq(true, null, false),
ArrayType(BooleanType))
+ val expectedWithNull = Seq("true", null, "false")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Boolean], ArrayType(BooleanType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
+ test("cast array element from date to string") {
+ val inputWithNull = Literal.create(
+ Seq(Date.valueOf("2024-01-01"), null, Date.valueOf("2024-01-03")),
+ ArrayType(DateType)
+ )
+ val expectedWithNull = Seq("2024-01-01", null, "2024-01-03")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputLeapYear = Literal.create(
+ Seq(Date.valueOf("2020-02-29")), // Leap day
+ ArrayType(DateType)
+ )
+ val expectedLeapYear = Seq("2020-02-29")
+ checkEvaluation(cast(inputLeapYear, ArrayType(StringType)),
expectedLeapYear)
+ }
+
+ test("cast array from timestamp to string") {
+ val inputWithNull = Literal.create(
+ Seq(Timestamp.valueOf("2023-01-01 12:00:00"), null,
Timestamp.valueOf("2023-12-31 23:59:59")),
+ ArrayType(TimestampType)
+ )
+ val expectedWithNull = Seq("2023-01-01 12:00:00", null, "2023-12-31
23:59:59")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Timestamp],
ArrayType(TimestampType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
testGluten("missing cases - from boolean") {
(DataTypeTestUtils.numericTypeWithoutDecimal + BooleanType).foreach {
t =>
diff --git
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index 9c0d966ef4..d8527ea639 100644
---
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -565,6 +565,11 @@ class ClickHouseTestSettings extends BackendTestSettings {
.exclude("SPARK-36924: Cast IntegralType to DayTimeIntervalType")
.exclude("SPARK-36924: Cast YearMonthIntervalType to IntegralType")
.exclude("SPARK-36924: Cast IntegralType to YearMonthIntervalType")
+ .exclude("cast array element from integer to string")
+ .exclude("cast array element from double to string")
+ .exclude("cast array element from bool to string")
+ .exclude("cast array element from date to string")
+ .exclude("cast array from timestamp to string")
enableSuite[GlutenCollectionExpressionsSuite]
.exclude("ArraysZip") // wait for
https://github.com/ClickHouse/ClickHouse/pull/69576
.exclude("Sequence of numbers")
diff --git
a/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
index e948601f29..07d3588885 100644
---
a/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
+++
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
@@ -44,6 +44,56 @@ class GlutenCastSuite extends CastWithAnsiOffSuite with
GlutenTestsTrait {
UDTRegistration.register(classOf[IExampleBaseType].getName,
classOf[ExampleBaseTypeUDT].getName)
UDTRegistration.register(classOf[IExampleSubType].getName,
classOf[ExampleSubTypeUDT].getName)
+ test("cast array element from integer to string") {
+ val inputWithNull = Literal.create(Seq(1, null, 3), ArrayType(IntegerType))
+ val expectedWithNull = Seq("1", null, "3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Int], ArrayType(IntegerType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+
+ val inputNegative = Literal.create(Seq(-1, 0, 999999),
ArrayType(IntegerType))
+ val expectedNegative = Seq("-1", "0", "999999")
+ checkEvaluation(cast(inputNegative, ArrayType(StringType)),
expectedNegative)
+ }
+
+ test("cast array element from double to string") {
+ val inputWithNull = Literal.create(Seq(1.1, null, 3.3),
ArrayType(DoubleType))
+ val expectedWithNull = Seq("1.1", null, "3.3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputScientific = Literal.create(Seq(1.23e4, -5.67e-3),
ArrayType(DoubleType))
+ val expectedScientific = Seq("12300.0", "-0.00567")
+ checkEvaluation(cast(inputScientific, ArrayType(StringType)),
expectedScientific)
+ }
+
+ test("cast array element from bool to string") {
+ val inputWithNull = Literal.create(Seq(true, null, false),
ArrayType(BooleanType))
+ val expectedWithNull = Seq("true", null, "false")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Boolean], ArrayType(BooleanType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
+ test("cast array element from date to string") {
+ val inputWithNull = Literal.create(
+ Seq(Date.valueOf("2024-01-01"), null, Date.valueOf("2024-01-03")),
+ ArrayType(DateType)
+ )
+ val expectedWithNull = Seq("2024-01-01", null, "2024-01-03")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputLeapYear = Literal.create(
+ Seq(Date.valueOf("2020-02-29")),
+ ArrayType(DateType)
+ )
+ val expectedLeapYear = Seq("2020-02-29")
+ checkEvaluation(cast(inputLeapYear, ArrayType(StringType)),
expectedLeapYear)
+ }
+
testGluten("missing cases - from boolean") {
(DataTypeTestUtils.numericTypeWithoutDecimal + BooleanType).foreach {
case t @ BooleanType =>
@@ -55,6 +105,19 @@ class GlutenCastSuite extends CastWithAnsiOffSuite with
GlutenTestsTrait {
}
}
+ test("cast array from timestamp to string") {
+ val inputWithNull = Literal.create(
+ Seq(Timestamp.valueOf("2023-01-01 12:00:00"), null,
Timestamp.valueOf("2023-12-31 23:59:59")),
+ ArrayType(TimestampType)
+ )
+ val expectedWithNull = Seq("2023-01-01 12:00:00", null, "2023-12-31
23:59:59")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Timestamp],
ArrayType(TimestampType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
testGluten("missing cases - from byte") {
DataTypeTestUtils.numericTypeWithoutDecimal.foreach {
t =>
diff --git
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index ff01c5452d..64e75994e0 100644
---
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -382,6 +382,11 @@ class ClickHouseTestSettings extends BackendTestSettings {
.exclude("SPARK-39749: cast Decimal to string")
.exclude("SPARK-42176: cast boolean to timestamp")
.exclude("null cast #2")
+ .exclude("cast array element from integer to string")
+ .exclude("cast array element from double to string")
+ .exclude("cast array element from bool to string")
+ .exclude("cast array element from date to string")
+ .exclude("cast array from timestamp to string")
enableSuite[GlutenCoalesceShufflePartitionsSuite]
.excludeByPrefix("determining the number of reducers")
.excludeCH("SPARK-46590 adaptive query execution works correctly with
broadcast join and union")
diff --git
a/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
index da611ca846..7debbf0c80 100644
---
a/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
+++
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenCastSuite.scala
@@ -44,6 +44,69 @@ class GlutenCastSuite extends CastWithAnsiOffSuite with
GlutenTestsTrait {
UDTRegistration.register(classOf[IExampleBaseType].getName,
classOf[ExampleBaseTypeUDT].getName)
UDTRegistration.register(classOf[IExampleSubType].getName,
classOf[ExampleSubTypeUDT].getName)
+ test("cast array element from integer to string") {
+ val inputWithNull = Literal.create(Seq(1, null, 3), ArrayType(IntegerType))
+ val expectedWithNull = Seq("1", null, "3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Int], ArrayType(IntegerType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+
+ val inputNegative = Literal.create(Seq(-1, 0, 999999),
ArrayType(IntegerType))
+ val expectedNegative = Seq("-1", "0", "999999")
+ checkEvaluation(cast(inputNegative, ArrayType(StringType)),
expectedNegative)
+ }
+
+ test("cast array element from double to string") {
+ val inputWithNull = Literal.create(Seq(1.1, null, 3.3),
ArrayType(DoubleType))
+ val expectedWithNull = Seq("1.1", null, "3.3")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputScientific = Literal.create(Seq(1.23e4, -5.67e-3),
ArrayType(DoubleType))
+ val expectedScientific = Seq("12300.0", "-0.00567")
+ checkEvaluation(cast(inputScientific, ArrayType(StringType)),
expectedScientific)
+ }
+
+ test("cast array element from bool to string") {
+ val inputWithNull = Literal.create(Seq(true, null, false),
ArrayType(BooleanType))
+ val expectedWithNull = Seq("true", null, "false")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Boolean], ArrayType(BooleanType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
+ test("cast array element from date to string") {
+ val inputWithNull = Literal.create(
+ Seq(Date.valueOf("2024-01-01"), null, Date.valueOf("2024-01-03")),
+ ArrayType(DateType)
+ )
+ val expectedWithNull = Seq("2024-01-01", null, "2024-01-03")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val inputLeapYear = Literal.create(
+ Seq(Date.valueOf("2020-02-29")),
+ ArrayType(DateType)
+ )
+ val expectedLeapYear = Seq("2020-02-29")
+ checkEvaluation(cast(inputLeapYear, ArrayType(StringType)),
expectedLeapYear)
+ }
+
+ test("cast array from timestamp to string") {
+ val inputWithNull = Literal.create(
+ Seq(Timestamp.valueOf("2023-01-01 12:00:00"), null,
Timestamp.valueOf("2023-12-31 23:59:59")),
+ ArrayType(TimestampType)
+ )
+ val expectedWithNull = Seq("2023-01-01 12:00:00", null, "2023-12-31
23:59:59")
+ checkEvaluation(cast(inputWithNull, ArrayType(StringType)),
expectedWithNull)
+
+ val emptyInput = Literal.create(Seq.empty[Timestamp],
ArrayType(TimestampType))
+ val expectedEmpty = Seq.empty[String]
+ checkEvaluation(cast(emptyInput, ArrayType(StringType)), expectedEmpty)
+ }
+
testGluten("missing cases - from boolean") {
(DataTypeTestUtils.numericTypeWithoutDecimal ++ Set(BooleanType)).foreach {
t =>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]