Skip to content

Commit db84681

Browse files
vladimirg-dbMaxGekk
authored andcommitted
[SPARK-49659][SQL] Add a nice user-facing error for scalar subqueries inside VALUES clause
### What changes were proposed in this pull request? Introduce a new `SCALAR_SUBQUERY_IN_VALUES` error, since we don't support scalar subqueries in the VALUES clause for now. ### Why are the changes needed? To make Spark user experience nicer. ### Does this PR introduce _any_ user-facing change? Yes, the exception type/message will be more descriptive ### How was this patch tested? - New unit test - Existing unit tests ### Was this patch authored or co-authored using generative AI tooling? No Closes #48118 from vladimirg-db/vladimirg-db/introduce-user-facing-exception-for-inline-tables-with-scalar-subqueries. Authored-by: Vladimir Golubev <[email protected]> Signed-off-by: Max Gekk <[email protected]>
1 parent 370453a commit db84681

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

common/utils/src/main/resources/error/error-conditions.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5330,6 +5330,11 @@
53305330
"<treeNode>"
53315331
]
53325332
},
5333+
"SCALAR_SUBQUERY_IN_VALUES" : {
5334+
"message" : [
5335+
"Scalar subqueries in the VALUES clause."
5336+
]
5337+
},
53335338
"UNSUPPORTED_CORRELATED_EXPRESSION_IN_JOIN_CONDITION" : {
53345339
"message" : [
53355340
"Correlated subqueries in the join predicate cannot reference both join inputs:",

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB
250250
context = u.origin.getQueryContext,
251251
summary = u.origin.context.summary)
252252

253+
case u: UnresolvedInlineTable if unresolvedInlineTableContainsScalarSubquery(u) =>
254+
throw QueryCompilationErrors.inlineTableContainsScalarSubquery(u)
255+
253256
case command: V2PartitionCommand =>
254257
command.table match {
255258
case r @ ResolvedTable(_, _, table, _) => table match {
@@ -1559,6 +1562,15 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB
15591562
case _ =>
15601563
}
15611564
}
1565+
1566+
private def unresolvedInlineTableContainsScalarSubquery(
1567+
unresolvedInlineTable: UnresolvedInlineTable) = {
1568+
unresolvedInlineTable.rows.exists { row =>
1569+
row.exists { expression =>
1570+
expression.exists(_.isInstanceOf[ScalarSubquery])
1571+
}
1572+
}
1573+
}
15621574
}
15631575

15641576
// a heap of the preempted error that only keeps the top priority element, representing the sole

sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4112,4 +4112,12 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat
41124112
"expr" -> expr.toString),
41134113
origin = expr.origin)
41144114
}
4115+
4116+
def inlineTableContainsScalarSubquery(inlineTable: LogicalPlan): Throwable = {
4117+
new AnalysisException(
4118+
errorClass = "UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.SCALAR_SUBQUERY_IN_VALUES",
4119+
messageParameters = Map.empty,
4120+
origin = inlineTable.origin
4121+
)
4122+
}
41154123
}

sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,6 +4909,21 @@ class SQLQuerySuite extends QueryTest with SharedSparkSession with AdaptiveSpark
49094909
)
49104910
}
49114911
}
4912+
4913+
test("SPARK-49659: Unsupported scalar subqueries in VALUES") {
4914+
checkError(
4915+
exception = intercept[AnalysisException](
4916+
sql("SELECT * FROM VALUES ((SELECT 1) + (SELECT 2))")
4917+
),
4918+
condition = "UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.SCALAR_SUBQUERY_IN_VALUES",
4919+
parameters = Map(),
4920+
context = ExpectedContext(
4921+
fragment = "VALUES ((SELECT 1) + (SELECT 2))",
4922+
start = 14,
4923+
stop = 45
4924+
)
4925+
)
4926+
}
49124927
}
49134928

49144929
case class Foo(bar: Option[String])

0 commit comments

Comments
 (0)