From 0fdca1f0df1ab5f7d843602fcee74f97f5be4f83 Mon Sep 17 00:00:00 2001 From: PengLei Date: Sun, 26 Sep 2021 18:43:26 +0800 Subject: [PATCH] [SPARK-36851][SQL] Incorrect parsing of negative ANSI typed interval literals ### What changes were proposed in this pull request? Handle incorrect parsing of negative ANSI typed interval literals [SPARK-36851](https://issues.apache.org/jira/browse/SPARK-36851) ### Why are the changes needed? Incorrect result: ``` spark-sql> select interval -'1' year; 1-0 ``` ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Add ut testcase Closes #34107 from Peng-Lei/SPARK-36851. Authored-by: PengLei Signed-off-by: Gengliang Wang --- .../sql/catalyst/parser/AstBuilder.scala | 9 +- .../resources/sql-tests/inputs/interval.sql | 12 +++ .../sql-tests/results/ansi/interval.sql.out | 98 ++++++++++++++++++- .../sql-tests/results/interval.sql.out | 98 ++++++++++++++++++- 4 files changed, 214 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala index 1b12994b6c..5ca0be4c38 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala @@ -2527,7 +2527,14 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg if (value.exists(Character.isLetter)) { throw QueryParsingErrors.invalidIntervalFormError(value, ctx) } - value + if (values(i).MINUS() == null) { + value + } else { + value.startsWith("-") match { + case true => value.replaceFirst("-", "") + case false => s"-$value" + } + } } else { values(i).getText } diff --git a/sql/core/src/test/resources/sql-tests/inputs/interval.sql b/sql/core/src/test/resources/sql-tests/inputs/interval.sql index 279c544113..a3daff659b 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/interval.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/interval.sql @@ -65,6 +65,18 @@ select interval +'-1-1' year to month; select interval - '1 2:3:4.001' day to second; select interval +'1 2:3:4.001' day to second; select interval -'-1 2:3:4.001' day to second; +select interval -'1' year; +select interval -'-1' year; +select interval -'11' month; +select interval -'-11' month; +select interval -'1' day; +select interval -'-1' day; +select interval -'23' hour; +select interval -'-23' hour; +select interval -'59' minute; +select interval -'-59' minute; +select interval -'59' second; +select interval -'-59' second; -- make intervals select make_interval(1); diff --git a/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out b/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out index 40c77744b1..9e7736a901 100644 --- a/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/ansi/interval.sql.out @@ -1,5 +1,5 @@ -- Automatically generated by SQLQueryTestSuite --- Number of queries: 257 +-- Number of queries: 269 -- !query @@ -474,6 +474,102 @@ struct 1 02:03:04.001000000 +-- !query +select interval -'1' year +-- !query schema +struct +-- !query output +-1-0 + + +-- !query +select interval -'-1' year +-- !query schema +struct +-- !query output +1-0 + + +-- !query +select interval -'11' month +-- !query schema +struct +-- !query output +-0-11 + + +-- !query +select interval -'-11' month +-- !query schema +struct +-- !query output +0-11 + + +-- !query +select interval -'1' day +-- !query schema +struct +-- !query output +-1 00:00:00.000000000 + + +-- !query +select interval -'-1' day +-- !query schema +struct +-- !query output +1 00:00:00.000000000 + + +-- !query +select interval -'23' hour +-- !query schema +struct +-- !query output +-0 23:00:00.000000000 + + +-- !query +select interval -'-23' hour +-- !query schema +struct +-- !query output +0 23:00:00.000000000 + + +-- !query +select interval -'59' minute +-- !query schema +struct +-- !query output +-0 00:59:00.000000000 + + +-- !query +select interval -'-59' minute +-- !query schema +struct +-- !query output +0 00:59:00.000000000 + + +-- !query +select interval -'59' second +-- !query schema +struct +-- !query output +-0 00:00:59.000000000 + + +-- !query +select interval -'-59' second +-- !query schema +struct +-- !query output +0 00:00:59.000000000 + + -- !query select make_interval(1) -- !query schema diff --git a/sql/core/src/test/resources/sql-tests/results/interval.sql.out b/sql/core/src/test/resources/sql-tests/results/interval.sql.out index 5f6af71a31..a8fa101a78 100644 --- a/sql/core/src/test/resources/sql-tests/results/interval.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/interval.sql.out @@ -1,5 +1,5 @@ -- Automatically generated by SQLQueryTestSuite --- Number of queries: 257 +-- Number of queries: 269 -- !query @@ -468,6 +468,102 @@ struct 1 02:03:04.001000000 +-- !query +select interval -'1' year +-- !query schema +struct +-- !query output +-1-0 + + +-- !query +select interval -'-1' year +-- !query schema +struct +-- !query output +1-0 + + +-- !query +select interval -'11' month +-- !query schema +struct +-- !query output +-0-11 + + +-- !query +select interval -'-11' month +-- !query schema +struct +-- !query output +0-11 + + +-- !query +select interval -'1' day +-- !query schema +struct +-- !query output +-1 00:00:00.000000000 + + +-- !query +select interval -'-1' day +-- !query schema +struct +-- !query output +1 00:00:00.000000000 + + +-- !query +select interval -'23' hour +-- !query schema +struct +-- !query output +-0 23:00:00.000000000 + + +-- !query +select interval -'-23' hour +-- !query schema +struct +-- !query output +0 23:00:00.000000000 + + +-- !query +select interval -'59' minute +-- !query schema +struct +-- !query output +-0 00:59:00.000000000 + + +-- !query +select interval -'-59' minute +-- !query schema +struct +-- !query output +0 00:59:00.000000000 + + +-- !query +select interval -'59' second +-- !query schema +struct +-- !query output +-0 00:00:59.000000000 + + +-- !query +select interval -'-59' second +-- !query schema +struct +-- !query output +0 00:00:59.000000000 + + -- !query select make_interval(1) -- !query schema