This is an automated email from the ASF dual-hosted git repository.
wenchen pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 010840880863 [SPARK-52148][SQL] Fix CREATE OR REPLACE function for SQL
user-defined TVFs
010840880863 is described below
commit 010840880863a1d1d09d96c3ed50b0c42e755ea9
Author: Allison Wang <[email protected]>
AuthorDate: Mon Jun 30 21:42:36 2025 +0800
[SPARK-52148][SQL] Fix CREATE OR REPLACE function for SQL user-defined TVFs
### What changes were proposed in this pull request?
This PR fixes CREATE OR REPLACE function for SQL user-defined table-valued
functions.
### Why are the changes needed?
To fix an issue when creating SQL TVFs.
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
Existing tests
### Was this patch authored or co-authored using generative AI tooling?
No
Closes #51191 from allisonwang-db/spark-52148-fix-tvf.
Authored-by: Allison Wang <[email protected]>
Signed-off-by: Wenchen Fan <[email protected]>
(cherry picked from commit 0afe9f5d13e28fa5b25b1ccedc6a96a39fc34967)
Signed-off-by: Wenchen Fan <[email protected]>
---
.../sql/catalyst/catalog/SessionCatalog.scala | 2 ++
.../sql-tests/analyzer-results/sql-udf.sql.out | 17 ++++------
.../test/resources/sql-tests/inputs/sql-udf.sql | 1 +
.../resources/sql-tests/results/sql-udf.sql.out | 37 +++++++---------------
4 files changed, 21 insertions(+), 36 deletions(-)
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalog.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalog.scala
index 3eb1b35d2419..531b453213ed 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalog.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalog.scala
@@ -1481,6 +1481,8 @@ class SessionCatalog(
// For a permanent function, because we loaded it to the
FunctionRegistry
// when it's first used, we also need to drop it from the
FunctionRegistry.
functionRegistry.dropFunction(qualifiedIdent)
+ } else if (tableFunctionRegistry.functionExists(qualifiedIdent)) {
+ tableFunctionRegistry.dropFunction(qualifiedIdent)
}
externalCatalog.dropFunction(db, funcName)
} else if (!ignoreIfNotExists) {
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf.sql.out
index 488387fc9019..a060e95dea85 100644
--- a/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf.sql.out
+++ b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf.sql.out
@@ -4043,6 +4043,12 @@ SET spark.sql.ansi.enabled=true
SetCommand (spark.sql.ansi.enabled,Some(true))
+-- !query
+DROP FUNCTION IF EXISTS foo3_3at
+-- !query analysis
+DropFunctionCommand spark_catalog.default.foo3_3at, true, false
+
+
-- !query
CREATE FUNCTION foo3_3a(x INT) RETURNS DOUBLE RETURN 1 / x
-- !query analysis
@@ -4112,16 +4118,7 @@ CreateSQLFunctionCommand spark_catalog.default.foo3_3a,
x INT, DOUBLE, 1 / x, fa
-- !query
CREATE OR REPLACE FUNCTION foo3_3at(x INT) RETURNS TABLE (a DOUBLE) RETURN
SELECT 1 / x
-- !query analysis
-org.apache.spark.sql.catalyst.analysis.FunctionAlreadyExistsException
-{
- "errorClass" : "ROUTINE_ALREADY_EXISTS",
- "sqlState" : "42723",
- "messageParameters" : {
- "existingRoutineType" : "routine",
- "newRoutineType" : "routine",
- "routineName" : "`default`.`foo3_3at`"
- }
-}
+CreateSQLFunctionCommand spark_catalog.default.foo3_3at, x INT, a DOUBLE,
SELECT 1 / x, true, false, false, true
-- !query
diff --git a/sql/core/src/test/resources/sql-tests/inputs/sql-udf.sql
b/sql/core/src/test/resources/sql-tests/inputs/sql-udf.sql
index 1cb749e77099..957a49c760cb 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/sql-udf.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/sql-udf.sql
@@ -745,6 +745,7 @@ SELECT foo3_2e1(
-- 3.3 Create and invoke function with different SQL configurations
SET spark.sql.ansi.enabled=true;
+DROP FUNCTION IF EXISTS foo3_3at;
CREATE FUNCTION foo3_3a(x INT) RETURNS DOUBLE RETURN 1 / x;
CREATE FUNCTION foo3_3at(x INT) RETURNS TABLE (a DOUBLE) RETURN SELECT 1 / x;
CREATE TEMPORARY FUNCTION foo3_3b(x INT) RETURNS DOUBLE RETURN 1 / x;
diff --git a/sql/core/src/test/resources/sql-tests/results/sql-udf.sql.out
b/sql/core/src/test/resources/sql-tests/results/sql-udf.sql.out
index dd96c3f49604..c000a292f2d4 100644
--- a/sql/core/src/test/resources/sql-tests/results/sql-udf.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/sql-udf.sql.out
@@ -3591,6 +3591,14 @@ struct<key:string,value:string>
spark.sql.ansi.enabled true
+-- !query
+DROP FUNCTION IF EXISTS foo3_3at
+-- !query schema
+struct<>
+-- !query output
+
+
+
-- !query
CREATE FUNCTION foo3_3a(x INT) RETURNS DOUBLE RETURN 1 / x
-- !query schema
@@ -3702,16 +3710,7 @@ CREATE OR REPLACE FUNCTION foo3_3at(x INT) RETURNS TABLE
(a DOUBLE) RETURN SELEC
-- !query schema
struct<>
-- !query output
-org.apache.spark.sql.catalyst.analysis.FunctionAlreadyExistsException
-{
- "errorClass" : "ROUTINE_ALREADY_EXISTS",
- "sqlState" : "42723",
- "messageParameters" : {
- "existingRoutineType" : "routine",
- "newRoutineType" : "routine",
- "routineName" : "`default`.`foo3_3at`"
- }
-}
+
-- !query
@@ -3741,23 +3740,9 @@ NULL
-- !query
SELECT * FROM foo3_3at(0)
-- !query schema
-struct<>
+struct<a:double>
-- !query output
-org.apache.spark.SparkArithmeticException
-{
- "errorClass" : "DIVIDE_BY_ZERO",
- "sqlState" : "22012",
- "messageParameters" : {
- "config" : "\"spark.sql.ansi.enabled\""
- },
- "queryContext" : [ {
- "objectType" : "",
- "objectName" : "",
- "startIndex" : 8,
- "stopIndex" : 12,
- "fragment" : "1 / x"
- } ]
-}
+NULL
-- !query
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]