diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala index 50fa6fb87e74f..63e778af889a5 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala @@ -406,6 +406,10 @@ object DateTimeUtils { // year should have exact four digits return None } + if (i < 2 && j < bytes.length) { + // For the `yyyy` and `yyyy-[m]m` formats, entire input must be consumed. + return None + } segments(i) = currentSegmentValue try { val localDate = LocalDate.of(segments(0), segments(1), segments(2)) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala index 2de9c41a30b98..c77c9aec68873 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala @@ -138,6 +138,9 @@ class DateTimeUtilsSuite extends SparkFunSuite { assert(stringToDate(UTF8String.fromString("015-03-18")).isEmpty) assert(stringToDate(UTF8String.fromString("015")).isEmpty) assert(stringToDate(UTF8String.fromString("02015")).isEmpty) + assert(stringToDate(UTF8String.fromString("1999 08 01")).isEmpty) + assert(stringToDate(UTF8String.fromString("1999-08 01")).isEmpty) + assert(stringToDate(UTF8String.fromString("1999 08")).isEmpty) } test("string to timestamp") { @@ -242,6 +245,9 @@ class DateTimeUtilsSuite extends SparkFunSuite { checkStringToTimestamp("2015-03-18T12:03.17-20:0", None) checkStringToTimestamp("2015-03-18T12:03.17-0:70", None) checkStringToTimestamp("2015-03-18T12:03.17-1:0:0", None) + checkStringToTimestamp("1999 08 01", None) + checkStringToTimestamp("1999-08 01", None) + checkStringToTimestamp("1999 08", None) // Truncating the fractional seconds timeZone = TimeZone.getTimeZone("GMT+00:00") diff --git a/sql/core/src/test/resources/sql-tests/results/pgSQL/date.sql.out b/sql/core/src/test/resources/sql-tests/results/pgSQL/date.sql.out index a0630b9f3f826..0d669ae7ce5b5 100644 --- a/sql/core/src/test/resources/sql-tests/results/pgSQL/date.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/pgSQL/date.sql.out @@ -198,17 +198,29 @@ struct -- !query 21 SELECT date '1999 Jan 08' -- !query 21 schema -struct +struct<> -- !query 21 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 Jan 08(line 1, pos 7) + +== SQL == +SELECT date '1999 Jan 08' +-------^^^ -- !query 22 SELECT date '1999 08 Jan' -- !query 22 schema -struct +struct<> -- !query 22 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 Jan(line 1, pos 7) + +== SQL == +SELECT date '1999 08 Jan' +-------^^^ -- !query 23 @@ -230,17 +242,29 @@ struct -- !query 25 SELECT date '1999 01 08' -- !query 25 schema -struct +struct<> -- !query 25 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 01 08(line 1, pos 7) + +== SQL == +SELECT date '1999 01 08' +-------^^^ -- !query 26 SELECT date '1999 08 01' -- !query 26 schema -struct +struct<> -- !query 26 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 01(line 1, pos 7) + +== SQL == +SELECT date '1999 08 01' +-------^^^ -- !query 27 @@ -254,17 +278,29 @@ struct -- !query 28 SELECT date '1999 Jan 08' -- !query 28 schema -struct +struct<> -- !query 28 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 Jan 08(line 1, pos 7) + +== SQL == +SELECT date '1999 Jan 08' +-------^^^ -- !query 29 SELECT date '1999 08 Jan' -- !query 29 schema -struct +struct<> -- !query 29 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 Jan(line 1, pos 7) + +== SQL == +SELECT date '1999 08 Jan' +-------^^^ -- !query 30 @@ -286,17 +322,29 @@ struct -- !query 32 SELECT date '1999 01 08' -- !query 32 schema -struct +struct<> -- !query 32 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 01 08(line 1, pos 7) + +== SQL == +SELECT date '1999 01 08' +-------^^^ -- !query 33 SELECT date '1999 08 01' -- !query 33 schema -struct +struct<> -- !query 33 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 01(line 1, pos 7) + +== SQL == +SELECT date '1999 08 01' +-------^^^ -- !query 34 @@ -318,17 +366,29 @@ struct -- !query 36 SELECT date '1999 Jan 08' -- !query 36 schema -struct +struct<> -- !query 36 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 Jan 08(line 1, pos 7) + +== SQL == +SELECT date '1999 Jan 08' +-------^^^ -- !query 37 SELECT date '1999 08 Jan' -- !query 37 schema -struct +struct<> -- !query 37 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 Jan(line 1, pos 7) + +== SQL == +SELECT date '1999 08 Jan' +-------^^^ -- !query 38 @@ -350,17 +410,29 @@ struct -- !query 40 SELECT date '1999 01 08' -- !query 40 schema -struct +struct<> -- !query 40 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 01 08(line 1, pos 7) + +== SQL == +SELECT date '1999 01 08' +-------^^^ -- !query 41 SELECT date '1999 08 01' -- !query 41 schema -struct +struct<> -- !query 41 output -1999-01-01 +org.apache.spark.sql.catalyst.parser.ParseException + +Cannot parse the DATE value: 1999 08 01(line 1, pos 7) + +== SQL == +SELECT date '1999 08 01' +-------^^^ -- !query 42