This is an automated email from the ASF dual-hosted git repository.

wenchen pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new 3edcf37  [SPARK-34421][SQL][3.0] Resolve temporary functions and views 
in views with CTEs
3edcf37 is described below

commit 3edcf379be8f3a84471e32c14120cc3f1a6edace
Author: Peter Toth <peter.t...@gmail.com>
AuthorDate: Mon Feb 22 04:42:02 2021 +0000

    [SPARK-34421][SQL][3.0] Resolve temporary functions and views in views with 
CTEs
    
    ### What changes were proposed in this pull request?
    This PR:
    - Fixes a bug that doesn't report analysis error when it should:
      ```
      CREATE TEMPORARY VIEW temp_view AS SELECT 0;
      CREATE VIEW view_on_temp_view AS WITH cte AS (SELECT * FROM temp_view) 
SELECT * FROM cte
      ```
      by properly checking temporary objects in view definitions with CTEs.
    
    ### Why are the changes needed?
    To fix a bug.
    
    ### Does this PR introduce _any_ user-facing change?
    Yes, analysis error is thrown as expected.
    
    ### How was this patch tested?
    Added new UT + existing ones.
    
    Closes #31592 from 
peter-toth/SPARK-34421-temp-functions-in-views-with-cte-3.0.
    
    Authored-by: Peter Toth <peter.t...@gmail.com>
    Signed-off-by: Wenchen Fan <wenc...@databricks.com>
---
 .../apache/spark/sql/execution/command/views.scala |  3 +-
 .../scala/org/apache/spark/sql/SQLQuerySuite.scala | 40 ++++++++++++++++++++++
 2 files changed, 42 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 991ebc3..ebba726 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
@@ -25,7 +25,7 @@ import 
org.apache.spark.sql.catalyst.analysis.{GlobalTempView, LocalTempView, Pe
 import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, 
CatalogTable, CatalogTableType, SessionCatalog}
 import org.apache.spark.sql.catalyst.expressions.{Alias, Attribute, 
AttributeReference, SubqueryExpression}
 import org.apache.spark.sql.catalyst.plans.QueryPlan
-import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, Project, View}
+import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, Project, 
View, With}
 import 
org.apache.spark.sql.connector.catalog.CatalogV2Implicits.NamespaceHelper
 import org.apache.spark.sql.internal.StaticSQLConf
 import org.apache.spark.sql.types.{BooleanType, MetadataBuilder, StringType}
@@ -180,6 +180,7 @@ case class CreateViewCommand(
             throw new AnalysisException(s"Not allowed to create a permanent 
view $name by " +
               s"referencing a temporary view ${nameParts.quoted}. " +
               "Please create a temp view instead by CREATE TEMP VIEW")
+          case w: With if !w.resolved => w.innerChildren.foreach(verify)
           case other if !other.resolved => other.expressions.flatMap(_.collect 
{
             // Traverse subquery plan for any unresolved relations.
             case e: SubqueryExpression => verify(e.plan)
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 409e645..88524d7 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
@@ -3650,6 +3650,46 @@ class SQLQuerySuite extends QueryTest with 
SharedSparkSession with AdaptiveSpark
       }
     }
   }
+
+  test("SPARK-34421: Resolve temporary objects in permanent views with CTEs") {
+    val tempFuncName = "temp_func"
+    withUserDefinedFunction((tempFuncName, true)) {
+      spark.udf.register(tempFuncName, identity[Int](_))
+
+      val tempViewName = "temp_view"
+      withTempView(tempViewName) {
+        sql(s"CREATE TEMPORARY VIEW $tempViewName AS SELECT 1")
+
+        val testViewName = "test_view"
+
+        val e = intercept[AnalysisException] {
+          sql(
+            s"""
+              |CREATE VIEW $testViewName AS
+              |WITH cte AS (
+              |  SELECT * FROM $tempViewName
+              |)
+              |SELECT * FROM cte
+              |""".stripMargin)
+        }
+        assert(e.message.contains("Not allowed to create a permanent view " +
+          s"`default`.`$testViewName` by referencing a temporary view 
$tempViewName"))
+
+        val e2 = intercept[AnalysisException] {
+          sql(
+            s"""
+              |CREATE VIEW $testViewName AS
+              |WITH cte AS (
+              |  SELECT $tempFuncName(0)
+              |)
+              |SELECT * FROM cte
+              |""".stripMargin)
+        }
+        assert(e2.message.contains("Not allowed to create a permanent view " +
+          s"`default`.`$testViewName` by referencing a temporary function 
`$tempFuncName`"))
+      }
+    }
+  }
 }
 
 case class Foo(bar: Option[String])


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org
For additional commands, e-mail: commits-h...@spark.apache.org

Reply via email to