diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index 38472f44fb59..57b3d33741e9 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -5330,6 +5330,11 @@ "" ] }, + "SCALAR_SUBQUERY_IN_VALUES" : { + "message" : [ + "Scalar subqueries in the VALUES clause." + ] + }, "UNSUPPORTED_CORRELATED_EXPRESSION_IN_JOIN_CONDITION" : { "message" : [ "Correlated subqueries in the join predicate cannot reference both join inputs:", diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala index a9fbe548ba39..752ff49e1f90 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala @@ -250,6 +250,9 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB context = u.origin.getQueryContext, summary = u.origin.context.summary) + case u: UnresolvedInlineTable if unresolvedInlineTableContainsScalarSubquery(u) => + throw QueryCompilationErrors.inlineTableContainsScalarSubquery(u) + case command: V2PartitionCommand => command.table match { case r @ ResolvedTable(_, _, table, _) => table match { @@ -1559,6 +1562,15 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB case _ => } } + + private def unresolvedInlineTableContainsScalarSubquery( + unresolvedInlineTable: UnresolvedInlineTable) = { + unresolvedInlineTable.rows.exists { row => + row.exists { expression => + expression.exists(_.isInstanceOf[ScalarSubquery]) + } + } + } } // a heap of the preempted error that only keeps the top priority element, representing the sole diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala index f1f8be3d1575..f268ef85ef1d 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala @@ -4112,4 +4112,12 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat "expr" -> expr.toString), origin = expr.origin) } + + def inlineTableContainsScalarSubquery(inlineTable: LogicalPlan): Throwable = { + new AnalysisException( + errorClass = "UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.SCALAR_SUBQUERY_IN_VALUES", + messageParameters = Map.empty, + origin = inlineTable.origin + ) + } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala index b7d0039446f3..9beceda26379 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala @@ -4909,6 +4909,21 @@ class SQLQuerySuite extends QueryTest with SharedSparkSession with AdaptiveSpark ) } } + + test("SPARK-49659: Unsupported scalar subqueries in VALUES") { + checkError( + exception = intercept[AnalysisException]( + sql("SELECT * FROM VALUES ((SELECT 1) + (SELECT 2))") + ), + condition = "UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.SCALAR_SUBQUERY_IN_VALUES", + parameters = Map(), + context = ExpectedContext( + fragment = "VALUES ((SELECT 1) + (SELECT 2))", + start = 14, + stop = 45 + ) + ) + } } case class Foo(bar: Option[String])