From 54a2febda6cfaa8fb5face8f0b6af028d914fa1d Mon Sep 17 00:00:00 2001 From: RoryQi <1242949407@qq.com> Date: Mon, 5 Jul 2021 01:43:50 +0800 Subject: [PATCH 1/4] [SPARK-36011][SQL] Disallow altering permanent views based on temporary views or UDFs --- .../spark/sql/execution/command/views.scala | 5 ++- .../sql/execution/SQLViewTestSuite.scala | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) 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 ebcd2776c714f..a3ca223e2a54c 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) 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 80e90198726c5..b0c728e31d51a 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,35 @@ class PersistedViewTestSuite extends SQLViewTestSuite with SharedSparkSession { } } } + + test("SPARK-36011: Disallow altering permanent views based on temporary views or UDFs") { + import testImplicits._ + val table = "t" + withTable(table) { + (1 to 10).toDF("id").write.saveAsTable(table) + val view = "v1" + val tView = "v2" + withView(view) { + withTempView(tView) { + sql(s"CREATE VIEW $view AS SELECT * FROM $table") + sql(s"CREATE TEMPORARY VIEW $tView AS SELECT * FROM $table") + var e = intercept[AnalysisException] { + sql(s"ALTER VIEW $view AS SELECT * FROM $tView") + }.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 $view AS SELECT $tempFunctionName(id) from $table") + }.getMessage + assert(e.contains("Not allowed to create a permanent view `default`.`v1` by " + + s"referencing a temporary function `$tempFunctionName`")) + } + } + } + } + } } From 66f498e62fe8dcf63f3c9324b9ad94d655638c9d Mon Sep 17 00:00:00 2001 From: RoryQi <1242949407@qq.com> Date: Tue, 6 Jul 2021 01:17:04 +0800 Subject: [PATCH 2/4] trigger test From 24a57a7f1cd75555ed28235e0e265d91f3a33dcc Mon Sep 17 00:00:00 2001 From: RoryQi <1242949407@qq.com> Date: Tue, 6 Jul 2021 11:26:27 +0800 Subject: [PATCH 3/4] address comments --- .../spark/sql/execution/command/views.scala | 1 - .../sql/execution/SQLViewTestSuite.scala | 19 ++++++++----------- 2 files changed, 8 insertions(+), 12 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 a3ca223e2a54c..5e92ce2195382 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 @@ -289,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 b0c728e31d51a..882eaf1c77d76 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 @@ -468,17 +468,14 @@ class PersistedViewTestSuite extends SQLViewTestSuite with SharedSparkSession { test("SPARK-36011: Disallow altering permanent views based on temporary views or UDFs") { import testImplicits._ - val table = "t" - withTable(table) { - (1 to 10).toDF("id").write.saveAsTable(table) - val view = "v1" - val tView = "v2" - withView(view) { - withTempView(tView) { - sql(s"CREATE VIEW $view AS SELECT * FROM $table") - sql(s"CREATE TEMPORARY VIEW $tView AS SELECT * FROM $table") + withTable("t") { + (1 to 10).toDF("id").write.saveAsTable("t") + withView("v1") { + withTempView("v2") { + sql(s"CREATE VIEW v1 AS SELECT * FROM t") + sql(s"CREATE TEMPORARY VIEW v2 AS SELECT * FROM t") var e = intercept[AnalysisException] { - sql(s"ALTER VIEW $view AS SELECT * FROM $tView") + sql(s"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")) @@ -487,7 +484,7 @@ class PersistedViewTestSuite extends SQLViewTestSuite with SharedSparkSession { withUserDefinedFunction(tempFunctionName -> true) { sql(s"CREATE TEMPORARY FUNCTION $tempFunctionName AS '$functionClass'") e = intercept[AnalysisException] { - sql(s"ALTER VIEW $view AS SELECT $tempFunctionName(id) from $table") + 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`")) From ee5e76e04c393be21d6c3637b82887d283261f36 Mon Sep 17 00:00:00 2001 From: RoryQi <1242949407@qq.com> Date: Tue, 6 Jul 2021 12:53:48 +0800 Subject: [PATCH 4/4] address comments --- .../org/apache/spark/sql/execution/SQLViewTestSuite.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 882eaf1c77d76..bc64f51ae8bbf 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 @@ -472,10 +472,10 @@ class PersistedViewTestSuite extends SQLViewTestSuite with SharedSparkSession { (1 to 10).toDF("id").write.saveAsTable("t") withView("v1") { withTempView("v2") { - sql(s"CREATE VIEW v1 AS SELECT * FROM t") - sql(s"CREATE TEMPORARY VIEW v2 AS SELECT * FROM t") + sql("CREATE VIEW v1 AS SELECT * FROM t") + sql("CREATE TEMPORARY VIEW v2 AS SELECT * FROM t") var e = intercept[AnalysisException] { - sql(s"ALTER VIEW v1 AS SELECT * FROM v2") + 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"))