diff --git a/sql/core/src/test/scala/org/apache/spark/sql/DatasetUnpivotSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/DatasetUnpivotSuite.scala index 2bac51d159da8..fac98e61d29d4 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/DatasetUnpivotSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/DatasetUnpivotSuite.scala @@ -535,6 +535,98 @@ class DatasetUnpivotSuite extends QueryTest "val"), longStructDataRows) } + + test("unpivot with struct expressions") { + checkAnswer( + wideDataDs.unpivot( + Array($"id"), + Array( + struct($"str1".as("str"), $"int1".cast(LongType).as("long")).as("str-int"), + struct($"str2".as("str"), $"long1".as("long")).as("str-long") + ), + "var", + "val"), + Seq( + Row(1, "str-int", Row("one", 1L)), + Row(1, "str-long", Row("One", 1L)), + Row(2, "str-int", Row("two", null)), + Row(2, "str-long", Row(null, 2L)), + Row(3, "str-int", Row(null, 3L)), + Row(3, "str-long", Row("three", null)), + Row(4, "str-int", Row(null, null)), + Row(4, "str-long", Row(null, null)) + ) + ) + + checkAnswer( + // struct field types and names must match + wideDataDs.unpivot( + Array($"id"), + Array( + struct($"str1".as("str"), $"int1".cast(LongType).as("long")).as("str-int"), + struct($"str2".as("str"), $"long1".as("long")).as("str-long") + ), + "var", + "val").select( + $"id", $"var", $"val.*" + ), + Seq( + Row(1, "str-int", "one", 1L), + Row(1, "str-long", "One", 1L), + Row(2, "str-int", "two", null), + Row(2, "str-long", null, 2L), + Row(3, "str-int", null, 3L), + Row(3, "str-long", "three", null), + Row(4, "str-int", null, null), + Row(4, "str-long", null, null) + ) + ) + + // different struct field types and names fail + val e1 = intercept[AnalysisException] { + wideDataDs.unpivot( + Array($"id"), + Array( + struct($"str1", $"int1").as("str-int"), + struct($"str2", $"long1").as("str-long") + ), + "var", + "val" + ) + } + checkError( + exception = e1, + errorClass = "UNPIVOT_VALUE_DATA_TYPE_MISMATCH", + parameters = Map( + "types" -> ( + """"STRUCT" (`str-int`), """ + + """"STRUCT" (`str-long`)""" + ) + ) + ) + + // different struct field names fail + val e2 = intercept[AnalysisException] { + wideDataDs.unpivot( + Array($"id"), + Array( + struct($"str1", $"int1".cast(LongType).as("int1")).as("str-int"), + struct($"str2", $"long1").as("str-long") + ), + "var", + "val") + } + checkError( + exception = e2, + errorClass = "UNPIVOT_VALUE_DATA_TYPE_MISMATCH", + parameters = Map( + "types" -> ( + """"STRUCT" (`str-int`), """ + + """"STRUCT" (`str-long`)""" + ) + ) + ) + } } case class WideData(id: Int, str1: String, str2: String, int1: Option[Int], long1: Option[Long])