This is an automated email from the ASF dual-hosted git repository.
maxgekk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new c3872cd4f1b7 [SPARK-46818][SQL] Improve error messages for Range with
non-foldable inputs
c3872cd4f1b7 is described below
commit c3872cd4f1b7c27956c067da11a26ae5e2829ed3
Author: allisonwang-db <[email protected]>
AuthorDate: Thu Jan 25 10:30:03 2024 +0300
[SPARK-46818][SQL] Improve error messages for Range with non-foldable inputs
### What changes were proposed in this pull request?
This PR improves the error messages for the `Range` function when the input
arguments are not foldable.
### Why are the changes needed?
To make error messages more user-friendly.
For example, before this PR, Spark throws an internal error:
```
SELECT * FROM range(0, (select 1));
[INTERNAL_ERROR] Cannot evaluate expression: scalar-subquery#1306 []
SQLSTATE: XX000
```
After this PR, the error message will be:
```
[NON_FOLDABLE_ARGUMENT] The function `range` requires the parameter `end`
to be a foldable expression of the type "BIGINT", but the actual argument is a
non-foldable. SQLSTATE: 42K08; line 1 pos 14
```
### Does this PR introduce _any_ user-facing change?
Yes. Error message improvement.
### How was this patch tested?
New SQL tests.
### Was this patch authored or co-authored using generative AI tooling?
No
Closes #44857 from allisonwang-db/spark-46818-fix-range.
Authored-by: allisonwang-db <[email protected]>
Signed-off-by: Max Gekk <[email protected]>
---
.../plans/logical/basicLogicalOperators.scala | 28 +++++++++----
.../table-valued-functions.sql.out | 44 ++++++++++++++++++++
.../sql-tests/inputs/table-valued-functions.sql | 4 ++
.../results/table-valued-functions.sql.out | 48 ++++++++++++++++++++++
4 files changed, 116 insertions(+), 8 deletions(-)
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/basicLogicalOperators.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/basicLogicalOperators.scala
index fbbae16130c0..7c2dfd31f4e3 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/basicLogicalOperators.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/basicLogicalOperators.scala
@@ -965,7 +965,12 @@ object Range {
if (SQLConf.get.ansiEnabled) AnsiTypeCoercion else TypeCoercion
}
- private def castAndEval[T](expression: Expression, dataType: DataType,
paramIndex: Int): T = {
+ private def castAndEval[T](
+ expression: Expression, dataType: DataType, paramIndex: Int, paramName:
String): T = {
+ if (!expression.foldable) {
+ throw QueryCompilationErrors.nonFoldableArgumentError(
+ "range", paramName, dataType)
+ }
typeCoercion.implicitCast(expression, dataType)
.map(_.eval())
.filter(_ != null)
@@ -975,11 +980,11 @@ object Range {
}.asInstanceOf[T]
}
- def toLong(expression: Expression, paramIndex: Int): Long =
- castAndEval[Long](expression, LongType, paramIndex)
+ def toLong(expression: Expression, paramIndex: Int, paramName: String): Long
=
+ castAndEval[Long](expression, LongType, paramIndex, paramName)
- def toInt(expression: Expression, paramIndex: Int): Int =
- castAndEval[Int](expression, IntegerType, paramIndex)
+ def toInt(expression: Expression, paramIndex: Int, paramName: String): Int =
+ castAndEval[Int](expression, IntegerType, paramIndex, paramName)
}
@ExpressionDescription(
@@ -1025,12 +1030,19 @@ case class Range(
require(step != 0, s"step ($step) cannot be 0")
def this(start: Expression, end: Expression, step: Expression, numSlices:
Expression) = {
- this(Range.toLong(start, 1), Range.toLong(end, 2), Range.toLong(step, 3),
- Some(Range.toInt(numSlices, 4)))
+ this(
+ Range.toLong(start, 1, "start"),
+ Range.toLong(end, 2, "end"),
+ Range.toLong(step, 3, "step"),
+ Some(Range.toInt(numSlices, 4, "numSlices")))
}
def this(start: Expression, end: Expression, step: Expression) =
- this(Range.toLong(start, 1), Range.toLong(end, 2), Range.toLong(step, 3),
None)
+ this(
+ Range.toLong(start, 1, "start"),
+ Range.toLong(end, 2, "end"),
+ Range.toLong(step, 3, "step"),
+ None)
def this(start: Expression, end: Expression) = this(start, end,
Literal.create(1L, LongType))
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/table-valued-functions.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/table-valued-functions.sql.out
index fe4c6ec26056..9ee8d741aed3 100644
---
a/sql/core/src/test/resources/sql-tests/analyzer-results/table-valued-functions.sql.out
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/table-valued-functions.sql.out
@@ -154,6 +154,50 @@ Project [i#xL]
+- Range (0, 2, step=1, splits=None)
+-- !query
+select * from range(0, (select 1))
+-- !query analysis
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "NON_FOLDABLE_ARGUMENT",
+ "sqlState" : "42K08",
+ "messageParameters" : {
+ "funcName" : "`range`",
+ "paramName" : "`end`",
+ "paramType" : "\"BIGINT\""
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 15,
+ "stopIndex" : 34,
+ "fragment" : "range(0, (select 1))"
+ } ]
+}
+
+
+-- !query
+select * from values (0, 1) t(c1, c2), lateral range(0, c2)
+-- !query analysis
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "NON_FOLDABLE_ARGUMENT",
+ "sqlState" : "42K08",
+ "messageParameters" : {
+ "funcName" : "`range`",
+ "paramName" : "`end`",
+ "paramType" : "\"BIGINT\""
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 48,
+ "stopIndex" : 59,
+ "fragment" : "range(0, c2)"
+ } ]
+}
+
+
-- !query
select * from explode(array(1, 2))
-- !query analysis
diff --git
a/sql/core/src/test/resources/sql-tests/inputs/table-valued-functions.sql
b/sql/core/src/test/resources/sql-tests/inputs/table-valued-functions.sql
index 79d427bc2099..9bf41f71d47f 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/table-valued-functions.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/table-valued-functions.sql
@@ -31,6 +31,10 @@ select * from RaNgE(2);
-- range call with alias
select i from range(0, 2) t(i);
+-- range with non-foldable input
+select * from range(0, (select 1));
+select * from values (0, 1) t(c1, c2), lateral range(0, c2);
+
-- explode
select * from explode(array(1, 2));
select * from explode(map('a', 1, 'b', 2));
diff --git
a/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
b/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
index a7e9ecd2543e..358217d3b190 100644
---
a/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
+++
b/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
@@ -191,6 +191,54 @@ struct<i:bigint>
1
+-- !query
+select * from range(0, (select 1))
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "NON_FOLDABLE_ARGUMENT",
+ "sqlState" : "42K08",
+ "messageParameters" : {
+ "funcName" : "`range`",
+ "paramName" : "`end`",
+ "paramType" : "\"BIGINT\""
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 15,
+ "stopIndex" : 34,
+ "fragment" : "range(0, (select 1))"
+ } ]
+}
+
+
+-- !query
+select * from values (0, 1) t(c1, c2), lateral range(0, c2)
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "NON_FOLDABLE_ARGUMENT",
+ "sqlState" : "42K08",
+ "messageParameters" : {
+ "funcName" : "`range`",
+ "paramName" : "`end`",
+ "paramType" : "\"BIGINT\""
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 48,
+ "stopIndex" : 59,
+ "fragment" : "range(0, c2)"
+ } ]
+}
+
+
-- !query
select * from explode(array(1, 2))
-- !query schema
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]