You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by we...@apache.org on 2026/08/21 18:42:52 UTC
(spark) branch master updated: [SPARK-58894][SQL] Detect cyclic view references in nested subqueries
This is an automated email from the ASF dual-hosted git repository.
cloud-fan 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 02c21a6f9c87 [SPARK-58894][SQL] Detect cyclic view references in nested subqueries
02c21a6f9c87 is described below
commit 02c21a6f9c87b70fa166b34c131353f74e1b7dc9
Author: Manu Zhang <ma...@apache.org>
AuthorDate: Sat Aug 22 02:42:36 2026 +0800
[SPARK-58894][SQL] Detect cyclic view references in nested subqueries
### What changes were proposed in this pull request?
Update `ViewHelper.checkCyclicViewReference` to traverse complete expression trees when
looking for subquery expressions. Add a regression case where a scalar subquery that
references the altered view is nested below an equality predicate.
### Why are the changes needed?
The current check only inspects top-level plan expressions. It detects an `EXISTS`
subquery when the subquery is the expression root, but misses scalar and other subqueries
nested inside larger expressions. A recursive view definition can therefore be accepted
and fail later during view resolution with the maximum nested-view-depth error.
### Does this PR introduce _any_ user-facing change?
Yes. `CREATE OR REPLACE VIEW` and `ALTER VIEW` now reject recursive references from
subqueries nested inside larger expressions with `RECURSIVE_VIEW`, matching root-level
subquery behavior.
### How was this patch tested?
Added a regression assertion to `SimpleSQLViewSuite` and ran:
```
SPARK_LOCAL_IP=127.0.0.1 build/sbt \
'sql/testOnly org.apache.spark.sql.execution.SimpleSQLViewSuite -- -z "correctly handle a cyclic view reference"'
build/sbt 'sql/scalastyle' 'sql/Test/scalastyle'
```
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Codex (GPT-5)
Closes #58146 from manuzhang/codex/fix-nested-view-cycle.
Authored-by: Manu Zhang <ma...@apache.org>
Signed-off-by: Wenchen Fan <we...@databricks.com>
---
.../org/apache/spark/sql/execution/command/views.scala | 4 ++--
.../scala/org/apache/spark/sql/execution/SQLViewSuite.scala | 13 +++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/views.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/views.scala
index 411682f35f6d..4338bd367fe0 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/views.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/views.scala
@@ -599,9 +599,9 @@ object ViewHelper extends SQLConfHelper with Logging with CapturesConfig {
plan.children.foreach(child => checkCyclicViewReference(child, path, viewIdent))
}
- // Detect cyclic references from subqueries.
+ // Detect cyclic references from subqueries nested in expressions.
plan.expressions.foreach { expr =>
- expr match {
+ expr.foreach {
case s: SubqueryExpression =>
checkCyclicViewReference(s.plan, path, viewIdent)
case _ => // Do nothing.
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewSuite.scala
index 3fb54d7c43d5..aef97c2a9314 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewSuite.scala
@@ -1018,6 +1018,19 @@ abstract class SQLViewSuite extends QueryTest {
s"`$SESSION_CATALOG_NAME`.`default`.`view2` -> " +
s"`$SESSION_CATALOG_NAME`.`default`.`view1`"))
)
+
+ // Detect cyclic view references from subqueries nested in larger expressions.
+ checkError(
+ exception = intercept[AnalysisException] {
+ sql("ALTER VIEW view1 AS SELECT * FROM jt WHERE id = (SELECT id FROM view2)")
+ },
+ condition = "RECURSIVE_VIEW",
+ parameters = Map(
+ "viewIdent" -> s"`$SESSION_CATALOG_NAME`.`default`.`view1`",
+ "newPath" -> (s"`$SESSION_CATALOG_NAME`.`default`.`view1` -> " +
+ s"`$SESSION_CATALOG_NAME`.`default`.`view2` -> " +
+ s"`$SESSION_CATALOG_NAME`.`default`.`view1`"))
+ )
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org