diff --git a/common/unsafe/src/main/java/org/apache/spark/unsafe/types/UTF8String.java b/common/unsafe/src/main/java/org/apache/spark/unsafe/types/UTF8String.java index 3754a1a0374a8..c5384669eb922 100644 --- a/common/unsafe/src/main/java/org/apache/spark/unsafe/types/UTF8String.java +++ b/common/unsafe/src/main/java/org/apache/spark/unsafe/types/UTF8String.java @@ -1294,6 +1294,52 @@ public boolean toByte(IntWrapper intWrapper) { return false; } + /** + * Parses UTF8String(trimmed if needed) to long. This method is used when ANSI is enabled. + * + * @return If string contains valid numeric value then it returns the long value otherwise a + * NumberFormatException is thrown. + */ + public long toLongExact() { + LongWrapper result = new LongWrapper(); + if (toLong(result)) { + return result.value; + } + throw new NumberFormatException("invalid input syntax for type numeric: " + this); + } + + /** + * Parses UTF8String(trimmed if needed) to int. This method is used when ANSI is enabled. + * + * @return If string contains valid numeric value then it returns the int value otherwise a + * NumberFormatException is thrown. + */ + public int toIntExact() { + IntWrapper result = new IntWrapper(); + if (toInt(result)) { + return result.value; + } + throw new NumberFormatException("invalid input syntax for type numeric: " + this); + } + + public short toShortExact() { + int value = this.toIntExact(); + short result = (short) value; + if (result == value) { + return result; + } + throw new NumberFormatException("invalid input syntax for type numeric: " + this); + } + + public byte toByteExact() { + int value = this.toIntExact(); + byte result = (byte) value; + if (result == value) { + return result; + } + throw new NumberFormatException("invalid input syntax for type numeric: " + this); + } + @Override public String toString() { return new String(getBytes(), StandardCharsets.UTF_8); diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala index fa27a48419dbb..4fd74a4e4658b 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala @@ -482,6 +482,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit // LongConverter private[this] def castToLong(from: DataType): Any => Any = from match { + case StringType if ansiEnabled => + buildCast[UTF8String](_, _.toLongExact()) case StringType => val result = new LongWrapper() buildCast[UTF8String](_, s => if (s.toLong(result)) result.value else null) @@ -499,6 +501,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit // IntConverter private[this] def castToInt(from: DataType): Any => Any = from match { + case StringType if ansiEnabled => + buildCast[UTF8String](_, _.toIntExact()) case StringType => val result = new IntWrapper() buildCast[UTF8String](_, s => if (s.toInt(result)) result.value else null) @@ -518,6 +522,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit // ShortConverter private[this] def castToShort(from: DataType): Any => Any = from match { + case StringType if ansiEnabled => + buildCast[UTF8String](_, _.toShortExact()) case StringType => val result = new IntWrapper() buildCast[UTF8String](_, s => if (s.toShort(result)) { @@ -559,6 +565,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit // ByteConverter private[this] def castToByte(from: DataType): Any => Any = from match { + case StringType if ansiEnabled => + buildCast[UTF8String](_, _.toByteExact()) case StringType => val result = new IntWrapper() buildCast[UTF8String](_, s => if (s.toByte(result)) { @@ -636,7 +644,12 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit // Please refer to https://github.com/apache/spark/pull/26640 changePrecision(Decimal(new JavaBigDecimal(s.toString.trim)), target) } catch { - case _: NumberFormatException => null + case _: NumberFormatException => + if (ansiEnabled) { + throw new NumberFormatException(s"invalid input syntax for type numeric: $s") + } else { + null + } }) case BooleanType => buildCast[Boolean](_, b => toPrecision(if (b) Decimal.ONE else Decimal.ZERO, target)) @@ -664,7 +677,12 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit val doubleStr = s.toString try doubleStr.toDouble catch { case _: NumberFormatException => - Cast.processFloatingPointSpecialLiterals(doubleStr, false) + val d = Cast.processFloatingPointSpecialLiterals(doubleStr, false) + if(ansiEnabled && d == null) { + throw new NumberFormatException(s"invalid input syntax for type numeric: $s") + } else { + d + } } }) case BooleanType => @@ -684,7 +702,12 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit val floatStr = s.toString try floatStr.toFloat catch { case _: NumberFormatException => - Cast.processFloatingPointSpecialLiterals(floatStr, true) + val f = Cast.processFloatingPointSpecialLiterals(floatStr, true) + if (ansiEnabled && f == null) { + throw new NumberFormatException(s"invalid input syntax for type numeric: $s") + } else { + f + } } }) case BooleanType => @@ -1128,12 +1151,17 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit from match { case StringType => (c, evPrim, evNull) => + val handleException = if (ansiEnabled) { + s"""throw new NumberFormatException("invalid input syntax for type numeric: $c");""" + } else { + s"$evNull =true;" + } code""" try { Decimal $tmp = Decimal.apply(new java.math.BigDecimal($c.toString().trim())); ${changePrecision(tmp, target, evPrim, evNull, canNullSafeCast)} } catch (java.lang.NumberFormatException e) { - $evNull = true; + $handleException } """ case BooleanType => @@ -1355,6 +1383,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit } private[this] def castToByteCode(from: DataType, ctx: CodegenContext): CastFunction = from match { + case StringType if ansiEnabled => + (c, evPrim, evNull) => code"$evPrim = $c.toByteExact();" case StringType => val wrapper = ctx.freshVariable("intWrapper", classOf[UTF8String.IntWrapper]) (c, evPrim, evNull) => @@ -1386,6 +1416,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit private[this] def castToShortCode( from: DataType, ctx: CodegenContext): CastFunction = from match { + case StringType if ansiEnabled => + (c, evPrim, evNull) => code"$evPrim = $c.toShortExact();" case StringType => val wrapper = ctx.freshVariable("intWrapper", classOf[UTF8String.IntWrapper]) (c, evPrim, evNull) => @@ -1415,6 +1447,8 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit } private[this] def castToIntCode(from: DataType, ctx: CodegenContext): CastFunction = from match { + case StringType if ansiEnabled => + (c, evPrim, evNull) => code"$evPrim = $c.toIntExact();" case StringType => val wrapper = ctx.freshVariable("intWrapper", classOf[UTF8String.IntWrapper]) (c, evPrim, evNull) => @@ -1443,9 +1477,10 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit } private[this] def castToLongCode(from: DataType, ctx: CodegenContext): CastFunction = from match { + case StringType if ansiEnabled => + (c, evPrim, evNull) => code"$evPrim = $c.toLongExact();" case StringType => val wrapper = ctx.freshVariable("longWrapper", classOf[UTF8String.LongWrapper]) - (c, evPrim, evNull) => code""" UTF8String.LongWrapper $wrapper = new UTF8String.LongWrapper(); @@ -1476,6 +1511,11 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit case StringType => val floatStr = ctx.freshVariable("floatStr", StringType) (c, evPrim, evNull) => + val handleNull = if (ansiEnabled) { + s"""throw new NumberFormatException("invalid input syntax for type numeric: $c");""" + } else { + s"$evNull = true;" + } code""" final String $floatStr = $c.toString(); try { @@ -1483,7 +1523,7 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit } catch (java.lang.NumberFormatException e) { final Float f = (Float) Cast.processFloatingPointSpecialLiterals($floatStr, true); if (f == null) { - $evNull = true; + $handleNull } else { $evPrim = f.floatValue(); } @@ -1507,6 +1547,11 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit case StringType => val doubleStr = ctx.freshVariable("doubleStr", StringType) (c, evPrim, evNull) => + val handleNull = if (ansiEnabled) { + s"""throw new NumberFormatException("invalid input syntax for type numeric: $c");""" + } else { + s"$evNull = true;" + } code""" final String $doubleStr = $c.toString(); try { @@ -1514,7 +1559,7 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit } catch (java.lang.NumberFormatException e) { final Double d = (Double) Cast.processFloatingPointSpecialLiterals($doubleStr, false); if (d == null) { - $evNull = true; + $handleNull } else { $evPrim = d.doubleValue(); } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala index 2d8f22c34ade7..7418870d9c731 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala @@ -284,7 +284,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { val gmtId = Option("GMT") checkEvaluation(cast("abdef", StringType), "abdef") - checkEvaluation(cast("abdef", DecimalType.USER_DEFAULT), null) checkEvaluation(cast("abdef", TimestampType, gmtId), null) checkEvaluation(cast("12.65", DecimalType.SYSTEM_DEFAULT), Decimal(12.65)) @@ -324,7 +323,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { checkEvaluation(cast("23", DecimalType.USER_DEFAULT), Decimal(23)) checkEvaluation(cast("23", ByteType), 23.toByte) checkEvaluation(cast("23", ShortType), 23.toShort) - checkEvaluation(cast("2012-12-11", DoubleType), null) checkEvaluation(cast(123, IntegerType), 123) checkEvaluation(cast(Literal.create(null, IntegerType), ShortType), null) @@ -410,15 +408,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { checkNullCast(ArrayType(StringType), ArrayType(IntegerType)) - { - val ret = cast(array, ArrayType(IntegerType, containsNull = true)) - assert(ret.resolved) - checkEvaluation(ret, Seq(123, null, null, null)) - } - { - val ret = cast(array, ArrayType(IntegerType, containsNull = false)) - assert(ret.resolved === false) - } { val ret = cast(array, ArrayType(BooleanType, containsNull = true)) assert(ret.resolved) @@ -429,15 +418,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { assert(ret.resolved === false) } - { - val ret = cast(array_notNull, ArrayType(IntegerType, containsNull = true)) - assert(ret.resolved) - checkEvaluation(ret, Seq(123, null, null)) - } - { - val ret = cast(array_notNull, ArrayType(IntegerType, containsNull = false)) - assert(ret.resolved === false) - } { val ret = cast(array_notNull, ArrayType(BooleanType, containsNull = true)) assert(ret.resolved) @@ -464,15 +444,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { checkNullCast(MapType(StringType, IntegerType), MapType(StringType, StringType)) - { - val ret = cast(map, MapType(StringType, IntegerType, valueContainsNull = true)) - assert(ret.resolved) - checkEvaluation(ret, Map("a" -> 123, "b" -> null, "c" -> null, "d" -> null)) - } - { - val ret = cast(map, MapType(StringType, IntegerType, valueContainsNull = false)) - assert(ret.resolved === false) - } { val ret = cast(map, MapType(StringType, BooleanType, valueContainsNull = true)) assert(ret.resolved) @@ -486,16 +457,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { val ret = cast(map, MapType(IntegerType, StringType, valueContainsNull = true)) assert(ret.resolved === false) } - - { - val ret = cast(map_notNull, MapType(StringType, IntegerType, valueContainsNull = true)) - assert(ret.resolved) - checkEvaluation(ret, Map("a" -> 123, "b" -> null, "c" -> null)) - } - { - val ret = cast(map_notNull, MapType(StringType, IntegerType, valueContainsNull = false)) - assert(ret.resolved === false) - } { val ret = cast(map_notNull, MapType(StringType, BooleanType, valueContainsNull = true)) assert(ret.resolved) @@ -546,23 +507,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { StructField("b", StringType, nullable = false), StructField("c", StringType, nullable = false)))) - { - val ret = cast(struct, StructType(Seq( - StructField("a", IntegerType, nullable = true), - StructField("b", IntegerType, nullable = true), - StructField("c", IntegerType, nullable = true), - StructField("d", IntegerType, nullable = true)))) - assert(ret.resolved) - checkEvaluation(ret, InternalRow(123, null, null, null)) - } - { - val ret = cast(struct, StructType(Seq( - StructField("a", IntegerType, nullable = true), - StructField("b", IntegerType, nullable = true), - StructField("c", IntegerType, nullable = false), - StructField("d", IntegerType, nullable = true)))) - assert(ret.resolved === false) - } { val ret = cast(struct, StructType(Seq( StructField("a", BooleanType, nullable = true), @@ -581,21 +525,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { assert(ret.resolved === false) } - { - val ret = cast(struct_notNull, StructType(Seq( - StructField("a", IntegerType, nullable = true), - StructField("b", IntegerType, nullable = true), - StructField("c", IntegerType, nullable = true)))) - assert(ret.resolved) - checkEvaluation(ret, InternalRow(123, null, null)) - } - { - val ret = cast(struct_notNull, StructType(Seq( - StructField("a", IntegerType, nullable = true), - StructField("b", IntegerType, nullable = true), - StructField("c", IntegerType, nullable = false)))) - assert(ret.resolved === false) - } { val ret = cast(struct_notNull, StructType(Seq( StructField("a", BooleanType, nullable = true), @@ -921,11 +850,6 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { Seq("nan", "nAn", " nan ").foreach { value => checkEvaluation(cast(value, DoubleType), Double.NaN) } - - // Invalid literals when casted to double and float results in null. - Seq(DoubleType, FloatType).foreach { dataType => - checkEvaluation(cast("badvalue", dataType), null) - } } private def testIntMaxAndMin(dt: DataType): Unit = { @@ -1054,7 +978,6 @@ class CastSuite extends CastSuiteBase { } } - test("cast from int") { checkCast(0, false) checkCast(1, true) @@ -1214,6 +1137,125 @@ class CastSuite extends CastSuiteBase { val set = CollectSet(Literal(1)) assert(Cast.canCast(set.dataType, ArrayType(StringType, false))) } + + test("Cast should output null for invalid strings when ANSI is not enabled.") { + withSQLConf(SQLConf.ANSI_ENABLED.key -> "false") { + checkEvaluation(cast("abdef", DecimalType.USER_DEFAULT), null) + checkEvaluation(cast("2012-12-11", DoubleType), null) + + // cast to array + val array = Literal.create(Seq("123", "true", "f", null), + ArrayType(StringType, containsNull = true)) + val array_notNull = Literal.create(Seq("123", "true", "f"), + ArrayType(StringType, containsNull = false)) + + { + val ret = cast(array, ArrayType(IntegerType, containsNull = true)) + assert(ret.resolved) + checkEvaluation(ret, Seq(123, null, null, null)) + } + { + val ret = cast(array, ArrayType(IntegerType, containsNull = false)) + assert(ret.resolved === false) + } + { + val ret = cast(array_notNull, ArrayType(IntegerType, containsNull = true)) + assert(ret.resolved) + checkEvaluation(ret, Seq(123, null, null)) + } + { + val ret = cast(array_notNull, ArrayType(IntegerType, containsNull = false)) + assert(ret.resolved === false) + } + + // cast from map + val map = Literal.create( + Map("a" -> "123", "b" -> "true", "c" -> "f", "d" -> null), + MapType(StringType, StringType, valueContainsNull = true)) + val map_notNull = Literal.create( + Map("a" -> "123", "b" -> "true", "c" -> "f"), + MapType(StringType, StringType, valueContainsNull = false)) + + { + val ret = cast(map, MapType(StringType, IntegerType, valueContainsNull = true)) + assert(ret.resolved) + checkEvaluation(ret, Map("a" -> 123, "b" -> null, "c" -> null, "d" -> null)) + } + { + val ret = cast(map, MapType(StringType, IntegerType, valueContainsNull = false)) + assert(ret.resolved === false) + } + { + val ret = cast(map_notNull, MapType(StringType, IntegerType, valueContainsNull = true)) + assert(ret.resolved) + checkEvaluation(ret, Map("a" -> 123, "b" -> null, "c" -> null)) + } + { + val ret = cast(map_notNull, MapType(StringType, IntegerType, valueContainsNull = false)) + assert(ret.resolved === false) + } + + // cast from struct + val struct = Literal.create( + InternalRow( + UTF8String.fromString("123"), + UTF8String.fromString("true"), + UTF8String.fromString("f"), + null), + StructType(Seq( + StructField("a", StringType, nullable = true), + StructField("b", StringType, nullable = true), + StructField("c", StringType, nullable = true), + StructField("d", StringType, nullable = true)))) + val struct_notNull = Literal.create( + InternalRow( + UTF8String.fromString("123"), + UTF8String.fromString("true"), + UTF8String.fromString("f")), + StructType(Seq( + StructField("a", StringType, nullable = false), + StructField("b", StringType, nullable = false), + StructField("c", StringType, nullable = false)))) + + { + val ret = cast(struct, StructType(Seq( + StructField("a", IntegerType, nullable = true), + StructField("b", IntegerType, nullable = true), + StructField("c", IntegerType, nullable = true), + StructField("d", IntegerType, nullable = true)))) + assert(ret.resolved) + checkEvaluation(ret, InternalRow(123, null, null, null)) + } + { + val ret = cast(struct, StructType(Seq( + StructField("a", IntegerType, nullable = true), + StructField("b", IntegerType, nullable = true), + StructField("c", IntegerType, nullable = false), + StructField("d", IntegerType, nullable = true)))) + assert(ret.resolved === false) + } + { + val ret = cast(struct_notNull, StructType(Seq( + StructField("a", IntegerType, nullable = true), + StructField("b", IntegerType, nullable = true), + StructField("c", IntegerType, nullable = true)))) + assert(ret.resolved) + checkEvaluation(ret, InternalRow(123, null, null)) + } + { + val ret = cast(struct_notNull, StructType(Seq( + StructField("a", IntegerType, nullable = true), + StructField("b", IntegerType, nullable = true), + StructField("c", IntegerType, nullable = false)))) + assert(ret.resolved === false) + } + + // Invalid literals when casted to double and float results in null. + Seq(DoubleType, FloatType).foreach { dataType => + checkEvaluation(cast("badvalue", dataType), null) + } + } + } } /** @@ -1229,4 +1271,29 @@ class AnsiCastSuite extends CastSuiteBase { case _ => AnsiCast(Literal(v), targetType, timeZoneId) } } + + test("cast from invalid string to numeric should throw NumberFormatException") { + // cast to IntegerType + Seq(IntegerType, ShortType, ByteType, LongType).foreach { dataType => + val array = Literal.create(Seq("123", "true", "f", null), + ArrayType(StringType, containsNull = true)) + checkExceptionInExpression[NumberFormatException]( + cast(array, ArrayType(dataType, containsNull = true)), "invalid input") + checkExceptionInExpression[NumberFormatException]( + cast("string", dataType), "invalid input") + checkExceptionInExpression[NumberFormatException]( + cast("123-string", dataType), "invalid input") + checkExceptionInExpression[NumberFormatException]( + cast("2020-07-19", dataType), "invalid input") + } + + Seq(DoubleType, FloatType, DecimalType.USER_DEFAULT).foreach { dataType => + checkExceptionInExpression[NumberFormatException]( + cast("string", dataType), "invalid input") + checkExceptionInExpression[NumberFormatException]( + cast("123.000.00", dataType), "invalid input") + checkExceptionInExpression[NumberFormatException]( + cast("abc.com", dataType), "invalid input") + } + } } diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/float4.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/float4.sql.out index 64608a349b610..7ca4c7eb8aa30 100644 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/float4.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/float4.sql.out @@ -93,25 +93,28 @@ struct -- !query 11 SELECT float('N A N') -- !query 11 schema -struct +struct<> -- !query 11 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: N A N -- !query 12 SELECT float('NaN x') -- !query 12 schema -struct +struct<> -- !query 12 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: NaN x -- !query 13 SELECT float(' INFINITY x') -- !query 13 schema -struct +struct<> -- !query 13 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: INFINITY x -- !query 14 @@ -141,9 +144,10 @@ NaN -- !query 17 SELECT float(decimal('nan')) -- !query 17 schema -struct +struct<> -- !query 17 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: nan -- !query 18 diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/float8.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/float8.sql.out index d38e36e956985..9d170d2fd8898 100644 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/float8.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/float8.sql.out @@ -125,25 +125,28 @@ struct -- !query 15 SELECT double('N A N') -- !query 15 schema -struct +struct<> -- !query 15 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: N A N -- !query 16 SELECT double('NaN x') -- !query 16 schema -struct +struct<> -- !query 16 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: NaN x -- !query 17 SELECT double(' INFINITY x') -- !query 17 schema -struct +struct<> -- !query 17 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: INFINITY x -- !query 18 @@ -173,9 +176,10 @@ NaN -- !query 21 SELECT double(decimal('nan')) -- !query 21 schema -struct +struct<> -- !query 21 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: nan -- !query 22 diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/text.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/text.sql.out index 311b0eb5a5844..6faa5b6924460 100755 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/text.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/text.sql.out @@ -62,17 +62,19 @@ struct -- !query 7 select string('four: ') || 2+2 -- !query 7 schema -struct<(CAST(concat(CAST(four: AS STRING), CAST(2 AS STRING)) AS DOUBLE) + CAST(2 AS DOUBLE)):double> +struct<> -- !query 7 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: four: 2 -- !query 8 select 'four: ' || 2+2 -- !query 8 schema -struct<(CAST(concat(four: , CAST(2 AS STRING)) AS DOUBLE) + CAST(2 AS DOUBLE)):double> +struct<> -- !query 8 output -NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: four: 2 -- !query 9 diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part2.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part2.sql.out index 0d2c78847b97c..9183eb659237e 100644 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part2.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part2.sql.out @@ -452,15 +452,10 @@ from numerics window w as (order by f_numeric range between 1.1 preceding and 'NaN' following) -- !query 28 schema -struct +struct<> -- !query 28 output -1 -3 NULL NULL -2 -1 NULL NULL -3 0 NULL NULL -4 1 NULL NULL -5 1 NULL NULL -6 2 NULL NULL -7 100 NULL NULL +java.lang.NumberFormatException +invalid input syntax for type numeric: NaN -- !query 29 diff --git a/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part4.sql.out b/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part4.sql.out index 54ceacd3b3b3e..e1c0499b32143 100644 --- a/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part4.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/postgreSQL/window_part4.sql.out @@ -498,10 +498,7 @@ SELECT a, b, SUM(b) OVER(ORDER BY A ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) FROM (VALUES(1,1),(2,2),(3,(cast('nan' as int))),(4,3),(5,4)) t(a,b) -- !query 38 schema -struct +struct<> -- !query 38 output -1 1 1 -2 2 3 -3 NULL 2 -4 3 3 -5 4 7 +org.apache.spark.sql.AnalysisException +failed to evaluate expression CAST('nan' AS INT): invalid input syntax for type numeric: nan; line 3 pos 6