This is an automated email from the ASF dual-hosted git repository.
MaxGekk pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-4.x by this push:
new 477d916c59f9 [SPARK-57756][SQL] Move SQL UDF resolution SQLConf
construction to common code
477d916c59f9 is described below
commit 477d916c59f94e0b672dbf7b2ac1585b018e8916
Author: daniel-lunin-db <[email protected]>
AuthorDate: Wed Jul 1 00:36:34 2026 +0200
[SPARK-57756][SQL] Move SQL UDF resolution SQLConf construction to common
code
SessionCatalog.makeSQLFunctionPlan and the ResolveSQLFunctions /
ResolveSQLTableFunctions analyzer rules each inline the same throwaway-SQLConf
construction used to resolve a SQL UDF body: new SQLConf, seed from the
function's stored configs, then either set ANSI unconditionally or overlay the
session's retained resolution configs. Move it into a common
Analyzer.buildSQLFunctionConf helper, parameterized by alwaysSetAnsiValue and
applySessionOverrides, and have the three call sites de [...]
### What changes were proposed in this pull request?
`SessionCatalog.makeSQLFunctionPlan` and the `ResolveSQLFunctions` /
`ResolveSQLTableFunctions` analyzer rules each inline the same
throwaway-`SQLConf`
construction used to resolve a SQL UDF body. This moves it into a common
`Analyzer.buildSQLFunctionConf` helper, parameterized by
`alwaysSetAnsiValue` and
`applySessionOverrides`, and has the three call sites delegate to it.
### Why are the changes needed?
The three call sites carried the same conf-seeding logic. Unifying it
removes the
duplication and gives one place to reason about a SQL UDF body's resolution
conf.
### Does this PR introduce _any_ user-facing change?
No. The helper produces the same `SQLConf` the inline code did.
### How was this patch tested?
Behavior-preserving extraction, covered by existing SQL UDF resolution
tests; CI on
this PR compiles and runs them.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Anthropic Claude Opus)
Closes #56895 from daniel-lunin-db/SPARK-57756.
Authored-by: daniel-lunin-db <[email protected]>
Signed-off-by: Max Gekk <[email protected]>
(cherry picked from commit e40dc30e4387fcd662069cb62b921c6470b6c548)
Signed-off-by: Max Gekk <[email protected]>
---
.../spark/sql/catalyst/analysis/Analyzer.scala | 45 +++++++++++++++++-----
.../sql/catalyst/catalog/SessionCatalog.scala | 7 ++--
2 files changed, 39 insertions(+), 13 deletions(-)
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
index 49d82e056f60..7fb7086449f6 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala
@@ -327,6 +327,33 @@ object Analyzer {
}
}
}
+
+ /**
+ * Builds the throwaway [[SQLConf]] used to resolve a SQL UDF body, seeded
from the function's
+ * stored configs. Call sites share this seeding but differ in how they
apply ANSI and session
+ * overrides, so both are parameters:
+ * - `alwaysSetAnsiValue` calls [[trySetAnsiValue]] unconditionally (the
SessionCatalog plan
+ * builders); when false, ANSI is set only as part of the session overlay
below (the
+ * [[Analyzer#ResolveSQLFunctions]] /
[[Analyzer#ResolveSQLTableFunctions]] rules).
+ * - `applySessionOverrides` overlays the active session's retained
resolution configs via
+ * [[retainResolutionConfigsForAnalysis]], gated on
+ * [[SQLConf.APPLY_SESSION_CONF_OVERRIDES_TO_FUNCTION_RESOLUTION]].
+ */
+ def buildSQLFunctionConf(
+ function: SQLFunction,
+ applySessionOverrides: Boolean,
+ alwaysSetAnsiValue: Boolean): SQLConf = {
+ val functionConf = new SQLConf()
+ function.getSQLConfigs.foreach { case (k, v) =>
functionConf.settings.put(k, v) }
+ if (alwaysSetAnsiValue) {
+ trySetAnsiValue(functionConf)
+ }
+ if (applySessionOverrides &&
+
conf.getConf(SQLConf.APPLY_SESSION_CONF_OVERRIDES_TO_FUNCTION_RESOLUTION)) {
+ retainResolutionConfigsForAnalysis(newConf = functionConf, existingConf
= conf)
+ }
+ functionConf
+ }
}
/**
@@ -2700,11 +2727,10 @@ class Analyzer(
val plan = v1SessionCatalog.makeSQLFunctionPlan(f.name, f.function,
f.inputs)
val resolved = SQLFunctionContext.withSQLFunction {
// Resolve the SQL function plan using its context.
- val newConf = new SQLConf()
- f.function.getSQLConfigs.foreach { case (k, v) =>
newConf.settings.put(k, v) }
- if
(conf.getConf(SQLConf.APPLY_SESSION_CONF_OVERRIDES_TO_FUNCTION_RESOLUTION)) {
- Analyzer.retainResolutionConfigsForAnalysis(newConf = newConf,
existingConf = conf)
- }
+ val newConf = Analyzer.buildSQLFunctionConf(
+ function = f.function,
+ applySessionOverrides = true,
+ alwaysSetAnsiValue = false)
SQLConf.withExistingConf(newConf) {
AnalysisContext.withAnalysisContext(f.function) {
executeSameContext(plan)
@@ -3010,11 +3036,10 @@ class Analyzer(
_.containsPattern(SQL_TABLE_FUNCTION)) {
case SQLTableFunction(name, function, inputs, output) =>
// Resolve the SQL table function plan using its function context.
- val newConf = new SQLConf()
- function.getSQLConfigs.foreach { case (k, v) =>
newConf.settings.put(k, v) }
- if
(conf.getConf(SQLConf.APPLY_SESSION_CONF_OVERRIDES_TO_FUNCTION_RESOLUTION)) {
- Analyzer.retainResolutionConfigsForAnalysis(newConf = newConf,
existingConf = conf)
- }
+ val newConf = Analyzer.buildSQLFunctionConf(
+ function = function,
+ applySessionOverrides = true,
+ alwaysSetAnsiValue = false)
val resolved = SQLConf.withExistingConf(newConf) {
val plan = v1SessionCatalog.makeSQLTableFunctionPlan(name, function,
inputs, output)
SQLFunctionContext.withSQLFunction {
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 d8461300f927..ae56a811a158 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
@@ -1893,9 +1893,10 @@ class SessionCatalog(
val funcName = function.name.funcName
// Use captured SQL configs when parsing a SQL function.
- val conf = new SQLConf()
- function.getSQLConfigs.foreach { case (k, v) => conf.settings.put(k, v) }
- Analyzer.trySetAnsiValue(conf)
+ val conf = Analyzer.buildSQLFunctionConf(
+ function = function,
+ applySessionOverrides = false,
+ alwaysSetAnsiValue = true)
SQLConf.withExistingConf(conf) {
val inputParam = function.inputParam
val returnType = function.getScalarFuncReturnType
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]