diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/variant/variantExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/variant/variantExpressions.scala index 723af5a4fe927..fda8fbc5efb47 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/variant/variantExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/variant/variantExpressions.scala @@ -373,6 +373,7 @@ case object VariantGet { VariantType => true case ArrayType(elementType, _) => checkDataType(elementType, allowStructsAndMaps) + case MapType(_: CharType | _: VarcharType, _, _) => false case MapType(_: StringType, valueType, _) if allowStructsAndMaps => checkDataType(valueType, allowStructsAndMaps) case StructType(fields) if allowStructsAndMaps => diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/variant/VariantExpressionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/variant/VariantExpressionSuite.scala index b3248609ae3ed..7dac7b0258599 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/variant/VariantExpressionSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/variant/VariantExpressionSuite.scala @@ -708,6 +708,31 @@ class VariantExpressionSuite extends SparkFunSuite with ExpressionEvalHelper { checkInvalidPath("$[\"\\\"\"]") } + test("SPARK-58672: validate char/varchar target types in variant_get") { + def check(dataType: DataType, expected: Boolean): Unit = { + assert( + variantGet("""{"a": 1}""", "$", dataType) + .checkInputDataTypes().isSuccess == expected) + } + + def targetTypes(stringType: StringType): Seq[DataType] = Seq( + stringType, + ArrayType(stringType), + MapType(stringType, IntegerType), + MapType(StringType, stringType), + StructType(Seq(StructField("v", stringType)))) + + targetTypes(StringType).foreach { dataType => + check(dataType, expected = true) + } + + Seq(CharType(10), VarcharType(10)).foreach { stringType => + targetTypes(stringType).foreach { dataType => + check(dataType, expected = false) + } + } + } + test("cast from variant") { // We do not test too many type combinations, as the cast implementation is mostly the same as // variant_get. @@ -986,6 +1011,30 @@ class VariantExpressionSuite extends SparkFunSuite with ExpressionEvalHelper { checkFailure(Map(1 -> 1), toVariantObject = true) } + test("SPARK-58672: validate char/varchar input types in to_variant_object") { + def check(dataType: DataType, expected: Boolean): Unit = { + assert( + ToVariantObject(Literal.create(null, dataType)) + .checkInputDataTypes().isSuccess == expected) + } + + def nestedTypes(stringType: StringType): Seq[DataType] = Seq( + ArrayType(stringType), + MapType(stringType, IntegerType), + MapType(StringType, stringType), + StructType(Seq(StructField("v", stringType)))) + + nestedTypes(StringType).foreach { dataType => + check(dataType, expected = true) + } + + Seq(CharType(10), VarcharType(10)).foreach { stringType => + nestedTypes(stringType).foreach { dataType => + check(dataType, expected = false) + } + } + } + test("schema_of_variant - unknown type") { val emptyMetadata = Array[Byte](VERSION, 0, 0)