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 ebcd2776c714..5e92ce219538 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 @@ -259,7 +259,10 @@ case class AlterViewAsCommand( def markAsAnalyzed(): LogicalPlan = copy(isAnalyzed = true) override def run(session: SparkSession): Seq[Row] = { - if (session.sessionState.catalog.isTempView(name)) { + val isTemporary = session.sessionState.catalog.isTempView(name) + verifyTemporaryObjectsNotExists(session.sessionState.catalog, isTemporary, name, query) + verifyAutoGeneratedAliasesNotExists(query, isTemporary, name) + if (isTemporary) { alterTemporaryView(session, query) } else { alterPermanentView(session, query) @@ -286,7 +289,6 @@ case class AlterViewAsCommand( } private def alterPermanentView(session: SparkSession, analyzedPlan: LogicalPlan): Unit = { - verifyAutoGeneratedAliasesNotExists(analyzedPlan, isTemporary = false, name) val viewMeta = session.sessionState.catalog.getTableMetadata(name) // Detect cyclic view reference on ALTER VIEW. diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewTestSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewTestSuite.scala index 80e90198726c..bc64f51ae8bb 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewTestSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/SQLViewTestSuite.scala @@ -465,4 +465,32 @@ class PersistedViewTestSuite extends SQLViewTestSuite with SharedSparkSession { } } } + + test("SPARK-36011: Disallow altering permanent views based on temporary views or UDFs") { + import testImplicits._ + withTable("t") { + (1 to 10).toDF("id").write.saveAsTable("t") + withView("v1") { + withTempView("v2") { + sql("CREATE VIEW v1 AS SELECT * FROM t") + sql("CREATE TEMPORARY VIEW v2 AS SELECT * FROM t") + var e = intercept[AnalysisException] { + sql("ALTER VIEW v1 AS SELECT * FROM v2") + }.getMessage + assert(e.contains("Not allowed to create a permanent view `default`.`v1` by " + + "referencing a temporary view v2")) + val tempFunctionName = "temp_udf" + val functionClass = "test.org.apache.spark.sql.MyDoubleAvg" + withUserDefinedFunction(tempFunctionName -> true) { + sql(s"CREATE TEMPORARY FUNCTION $tempFunctionName AS '$functionClass'") + e = intercept[AnalysisException] { + sql(s"ALTER VIEW v1 AS SELECT $tempFunctionName(id) from t") + }.getMessage + assert(e.contains("Not allowed to create a permanent view `default`.`v1` by " + + s"referencing a temporary function `$tempFunctionName`")) + } + } + } + } + } }