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

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


The following commit(s) were added to refs/heads/branch-3.3 by this push:
     new 4ad0b2c25eb [SPARK-38957][SQL] Use multipartIdentifier for parsing 
table-valued functions
4ad0b2c25eb is described below

commit 4ad0b2c25eba29694811445f72513629bf90e7e9
Author: allisonwang-db <[email protected]>
AuthorDate: Thu Apr 21 16:19:20 2022 +0800

    [SPARK-38957][SQL] Use multipartIdentifier for parsing table-valued 
functions
    
    This PR uses multipart identifiers when parsing table-valued functions.
    
    To make table-valued functions error messages consistent for 2-part names 
and n-part names. For example, before this PR:
    ```
    select * from a.b.c
    org.apache.spark.sql.catalyst.parser.ParseException:
    Invalid SQL syntax: Unsupported function name `a`.`b`.`c`(line 1, pos 14)
    
    == SQL ==
    select * from a.b.c(1)
    --------------^^^
    ```
    After this PR:
    ```
    Invalid SQL syntax: table valued function cannot specify database name 
(line 1, pos 14)
    
    == SQL ==
    SELECT * FROM a.b.c(1)
    --------------^^^
    ```
    
    No
    
    Unit test.
    
    Closes #36272 from allisonwang-db/spark-38957-parse-table-func.
    
    Authored-by: allisonwang-db <[email protected]>
    Signed-off-by: Wenchen Fan <[email protected]>
    (cherry picked from commit 8fe5bca1773521d967b82a920c6881f081155bc3)
    Signed-off-by: Wenchen Fan <[email protected]>
---
 .../apache/spark/sql/catalyst/parser/AstBuilder.scala | 19 ++++---------------
 .../apache/spark/sql/errors/QueryParsingErrors.scala  |  8 ++++++++
 .../spark/sql/catalyst/parser/PlanParserSuite.scala   |  5 ++++-
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
index 60e691ba4ac..7b3374e9332 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
@@ -1296,13 +1296,13 @@ class AstBuilder extends 
SqlBaseParserBaseVisitor[AnyRef] with SQLConfHelper wit
     } else {
       Seq.empty
     }
-    val name = getFunctionIdentifier(func.functionName)
-    if (name.database.nonEmpty) {
-      operationNotAllowed(s"table valued function cannot specify database 
name: $name", ctx)
+    val name = getFunctionMultiparts(func.functionName)
+    if (name.length > 1) {
+      throw QueryParsingErrors.invalidTableValuedFunctionNameError(name, ctx)
     }
 
     val tvf = UnresolvedTableValuedFunction(
-      name, func.expression.asScala.map(expression).toSeq, aliases)
+      name.asFunctionIdentifier, 
func.expression.asScala.map(expression).toSeq, aliases)
     tvf.optionalMap(func.tableAlias.strictIdentifier)(aliasPlan)
   }
 
@@ -1952,17 +1952,6 @@ class AstBuilder extends 
SqlBaseParserBaseVisitor[AnyRef] with SQLConfHelper wit
     }
   }
 
-  /**
-   * Get a function identifier consist by database (optional) and name.
-   */
-  protected def getFunctionIdentifier(ctx: FunctionNameContext): 
FunctionIdentifier = {
-    if (ctx.qualifiedName != null) {
-      visitFunctionName(ctx.qualifiedName)
-    } else {
-      FunctionIdentifier(ctx.getText, None)
-    }
-  }
-
   protected def getFunctionMultiparts(ctx: FunctionNameContext): Seq[String] = 
{
     if (ctx.qualifiedName != null) {
       ctx.qualifiedName().identifier().asScala.map(_.getText).toSeq
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala
index 39c1944bbba..38cff081eb5 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala
@@ -452,6 +452,14 @@ object QueryParsingErrors extends QueryErrorsBase {
       s"Specifying a database in CREATE TEMPORARY FUNCTION is not allowed: 
'$databaseName'", ctx)
   }
 
+  def invalidTableValuedFunctionNameError(
+      name: Seq[String],
+      ctx: TableValuedFunctionContext): Throwable = {
+    new ParseException(
+      "INVALID_SQL_SYNTAX",
+      Array("table valued function cannot specify database name ", 
toSQLId(name)), ctx)
+  }
+
   def unclosedBracketedCommentError(command: String, position: Origin): 
Throwable = {
     new ParseException(Some(command), "Unclosed bracketed comment", position, 
position)
   }
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala
index fb9fdfb8598..f6e94dc604b 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala
@@ -692,7 +692,10 @@ class PlanParserSuite extends AnalysisTest {
       UnresolvedTableValuedFunction("range", Literal(2) :: Nil, 
Seq.empty).select(star()))
     // SPARK-34627
     intercept("select * from default.range(2)",
-      "table valued function cannot specify database name: default.range")
+      "table valued function cannot specify database name")
+    // SPARK-38957
+    intercept("select * from spark_catalog.default.range(2)",
+      "table valued function cannot specify database name")
   }
 
   test("SPARK-20311 range(N) as alias") {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to