This is an automated email from the ASF dual-hosted git repository.
cloud-fan 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 64ac4fb16ab6 [SPARK-57188][SQL] Parameterless function takes
precedence over UDF parameter
64ac4fb16ab6 is described below
commit 64ac4fb16ab6fea04d9cb45e843bcfa0debd7604
Author: Dejan Krakovic <[email protected]>
AuthorDate: Tue Jun 2 14:00:59 2026 +0800
[SPARK-57188][SQL] Parameterless function takes precedence over UDF
parameter
### What changes were proposed in this pull request?
A parameterless built-in function (`current_user`, `current_date`,
`current_time`, `current_timestamp`, `user`, `session_user`, `grouping__id`)
now takes precedence over a SQL UDF parameter that shares its name. Previously
the UDF parameter alias shadowed the built-in, e.g. `CREATE FUNCTION
f(current_user STRING) RETURNS STRING RETURN current_user; SELECT f('alice')`
returned `'alice'` instead of the actual current user.
SQL UDF input-parameter aliases are marked with a named `Metadata` key,
`SessionCatalog.SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY`. Producers are
`SessionCatalog.makeSQLFunctionPlan` and `CreateSQLFunctionCommand` (CREATE
time). Storing the marker in `Metadata` (rather than a `TreeNodeTag`) lets it
propagate automatically through `Alias.toAttribute` and `AttributeReference`
copies.
In `ColumnResolutionHelper`, when name-based resolution returns an
attribute carrying this metadata, `LiteralFunctionResolution` is preferred over
it. Real columns from relations (no marker) still win, preserving the overall
precedence (column > parameterless function > UDF parameter).
The new behavior is gated behind a legacy kill-switch,
`spark.sql.legacy.allowUdfParameterToShadowParameterlessFunction` (default
`false`); set to `true` to restore the previous behavior.
### Why are the changes needed?
To match the documented SQL name resolution rules: a parameterless built-in
function should not be shadowed by a same-named UDF parameter.
### Does this PR introduce _any_ user-facing change?
Yes. A SQL UDF parameter named like a parameterless built-in function no
longer shadows that function in the function body. The legacy conf restores the
old behavior.
### How was this patch tested?
Added golden-file tests `sql-udf-name-precedence(.legacy)` and
`parameterless-function-name-precedence(.legacy)` covering column > param, LCA
> param, outer-ref > param, parameterless function > param (scalar and table
UDF), param > session variable, nested-UDF inner-scope binding, and the legacy
(flag-on) behavior. All 4 scenarios pass.
### Was this patch authored or co-authored using generative AI tooling?
Yes, co-authored using Claude code.
Closes #56239 from dejankrak-db/paramless-func-over-udf-param-oss.
Authored-by: Dejan Krakovic <[email protected]>
Signed-off-by: Wenchen Fan <[email protected]>
(cherry picked from commit e9f81257347fcd4009c7df4c7bf4395d19d9f77f)
Signed-off-by: Wenchen Fan <[email protected]>
---
.../catalyst/analysis/ColumnResolutionHelper.scala | 31 +-
.../sql/catalyst/catalog/SessionCatalog.scala | 24 +-
.../org/apache/spark/sql/internal/SQLConf.scala | 13 +
.../command/CreateSQLFunctionCommand.scala | 16 +-
...terless-function-name-precedence-legacy.sql.out | 127 ++++++++
.../parameterless-function-name-precedence.sql.out | 127 ++++++++
.../sql-udf-name-precedence-legacy.sql.out | 293 +++++++++++++++++
.../sql-udf-name-precedence.sql.out | 320 ++++++++++++++++++
...rameterless-function-name-precedence-legacy.sql | 3 +
.../parameterless-function-name-precedence.sql | 48 +++
.../inputs/sql-udf-name-precedence-legacy.sql | 3 +
.../sql-tests/inputs/sql-udf-name-precedence.sql | 96 ++++++
...terless-function-name-precedence-legacy.sql.out | 131 ++++++++
.../parameterless-function-name-precedence.sql.out | 131 ++++++++
.../results/sql-udf-name-precedence-legacy.sql.out | 327 +++++++++++++++++++
.../results/sql-udf-name-precedence.sql.out | 360 +++++++++++++++++++++
16 files changed, 2039 insertions(+), 11 deletions(-)
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ColumnResolutionHelper.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ColumnResolutionHelper.scala
index 0c8ecbab48ec..eaa61a2a9163 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ColumnResolutionHelper.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ColumnResolutionHelper.scala
@@ -23,6 +23,7 @@ import scala.collection.mutable
import org.apache.spark.internal.Logging
import org.apache.spark.sql.AnalysisException
+import org.apache.spark.sql.catalyst.catalog.SessionCatalog
import org.apache.spark.sql.catalyst.expressions._
import
org.apache.spark.sql.catalyst.expressions.SubExprUtils.wrapOuterReference
import org.apache.spark.sql.catalyst.plans.logical._
@@ -147,8 +148,20 @@ trait ColumnResolutionHelper extends Logging with
DataTypeErrorsBase {
// When strict DataFrame column resolution is disabled, we also
allow name-based
// resolution as a fallback for tagged attributes.
val result = withPosition(u) {
- resolveColumnByName(nameParts)
- .orElse(LiteralFunctionResolution.resolve(nameParts))
+ // A parameterless built-in function takes precedence over a SQL
UDF parameter
+ // that happens to share its name (per the documented SQL name
resolution rules).
+ // Real columns from relations -- which don't carry the
+ // SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY -- continue to win as
before.
+ // Gated by a legacy kill-switch conf so the pre-fix behavior can
be restored.
+ val column = resolveColumnByName(nameParts)
+ val resolved = column match {
+ case Some(c) if isSQLFunctionParameterAlias(c) && !conf.getConf(
+
SQLConf.LEGACY_ALLOW_UDF_PARAMETER_TO_SHADOW_PARAMETERLESS_FUNCTION) =>
+ LiteralFunctionResolution.resolve(nameParts).orElse(column)
+ case Some(_) => column
+ case None => LiteralFunctionResolution.resolve(nameParts)
+ }
+ resolved
.map {
// We trim unnecessary alias here. Note that, we cannot trim
the alias at top-level,
// as we should resolve `UnresolvedAttribute` to a named
expression. The caller side
@@ -696,4 +709,18 @@ trait ColumnResolutionHelper extends Logging with
DataTypeErrorsBase {
r.expressions.forall(_.references.subsetOf(outputSet))
}
}
+
+ /**
+ * True if `e` originates from a SQL UDF input parameter alias, as marked by
+ * `SessionCatalog.SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY` at
parameter-alias
+ * construction sites. Unwraps `OuterReference` so callers that pass
post-outer-resolution
+ * expressions still get a correct answer; the metadata lives on the
underlying named
+ * expression.
+ */
+ private def isSQLFunctionParameterAlias(e: Expression): Boolean = e match {
+ case OuterReference(inner) => isSQLFunctionParameterAlias(inner)
+ case n: NamedExpression =>
+
n.metadata.contains(SessionCatalog.SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY)
+ case _ => false
+ }
}
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 1b36a29438c9..fd700f1ee013 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
@@ -60,6 +60,13 @@ import org.apache.spark.util.Utils
object SessionCatalog {
val DEFAULT_DATABASE = "default"
+ /**
+ * Metadata key marking an Alias / Attribute as originating from a SQL UDF
input parameter.
+ * Consumed by name resolution: a parameterless built-in function takes
precedence over a
+ * tagged alias of the same name.
+ */
+ val SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY: String = "__funcInputAlias"
+
/**
* Kind of session-scoped function namespace for lookup/resolve.
* Used by the kind-based API to avoid separate methods per
@@ -1880,11 +1887,6 @@ class SessionCatalog(
name: String,
function: SQLFunction,
input: Seq[Expression]): LogicalPlan = {
- def metaForFuncInputAlias = {
- new MetadataBuilder()
- .putString("__funcInputAlias", "true")
- .build()
- }
assert(!function.isTableFunc,
"Function '" + function.name + "' is a table function. " +
"Use makeSQLTableFunctionPlan() instead of makeSQLFunctionPlan().")
@@ -1941,6 +1943,9 @@ class SessionCatalog(
}
}
+ val funcInputMetadata = new MetadataBuilder()
+
.putBoolean(SessionCatalog.SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY, true)
+ .build()
paddedInput.zip(param.fields).map {
case (expr, param) =>
// Add outer references to all resolved attributes and outer
references in the function
@@ -1950,10 +1955,11 @@ class SessionCatalog(
case a: Attribute if a.resolved => OuterReference(a)
case o: OuterReference => OuterReference(o)
}
+ // Mark the alias as function input so name resolution can give a
parameterless
+ // built-in function precedence over a same-named UDF parameter.
Alias(Cast(outer, param.dataType), param.name)(
qualifier = qualifier,
- // mark the alias as function input
- explicitMetadata = Some(metaForFuncInputAlias))
+ explicitMetadata = Some(funcInputMetadata))
}
}.getOrElse(Nil)
@@ -2046,6 +2052,10 @@ class SessionCatalog(
val outer = expr.transform {
case a: Attribute => OuterReference(a)
}
+ // No SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY marker here: a table
UDF body references
+ // its parameter as an outer reference (the param lives in the
lateral join's left
+ // child), so resolveColumnByName returns None and a parameterless
built-in function
+ // already wins via the pre-existing "function beats outer
reference" precedence.
Alias(Cast(outer, param.dataType), param.name)(qualifier = qualifier)
}
val inputPlan = Project(inputCast, OneRowRelation())
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
index 41a511666af8..7fadd084fe72 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
@@ -3651,6 +3651,19 @@ object SQLConf {
.booleanConf
.createWithDefault(false)
+ val LEGACY_ALLOW_UDF_PARAMETER_TO_SHADOW_PARAMETERLESS_FUNCTION =
+
buildConf("spark.sql.legacy.allowUdfParameterToShadowParameterlessFunction")
+ .internal()
+ .doc("When true (legacy behavior), a SQL UDF parameter alias shadows a
parameterless " +
+ "built-in function (current_user, current_date, current_time,
current_timestamp, " +
+ "user, session_user, grouping__id) of the same name. When false (the
default), the " +
+ "parameterless built-in function takes precedence, matching the
documented name " +
+ "resolution rules.")
+ .version("4.2.0")
+ .withBindingPolicy(ConfigBindingPolicy.SESSION)
+ .booleanConf
+ .createWithDefault(false)
+
val ALLOW_NON_EMPTY_LOCATION_IN_CTAS =
buildConf("spark.sql.legacy.allowNonEmptyLocationInCTAS")
.internal()
diff --git
a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/CreateSQLFunctionCommand.scala
b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/CreateSQLFunctionCommand.scala
index 9bfdff127c5a..a597087085b4 100644
---
a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/CreateSQLFunctionCommand.scala
+++
b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/CreateSQLFunctionCommand.scala
@@ -32,7 +32,7 @@ import org.apache.spark.sql.connector.catalog.CatalogManager
import
org.apache.spark.sql.connector.catalog.CatalogV2Implicits.MultipartIdentifierHelper
import org.apache.spark.sql.errors.QueryCompilationErrors
import
org.apache.spark.sql.execution.command.CreateUserDefinedFunctionCommand._
-import org.apache.spark.sql.types.{DataType, StructField, StructType}
+import org.apache.spark.sql.types.{DataType, MetadataBuilder, StructField,
StructType}
/**
* The DDL command that creates a SQL function.
@@ -109,6 +109,18 @@ case class CreateSQLFunctionCommand(
// Qualify the input parameters with the function name so that
attributes referencing
// the function input parameters can be resolved correctly.
val qualifier = Seq(name.funcName)
+ // Mark scalar UDF parameter aliases as function input so name
resolution can give a
+ // parameterless built-in function precedence over a same-named UDF
parameter. Table UDF
+ // bodies reference parameters as outer references, where a
parameterless function already
+ // wins via the pre-existing "function beats outer reference"
precedence, so the marker is
+ // not applied (and would not be consumed) there.
+ val funcInputMetadata = if (isTableFunc) {
+ None
+ } else {
+ Some(new MetadataBuilder()
+
.putBoolean(SessionCatalog.SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY, true)
+ .build())
+ }
val input = param.map(p => Alias(
{
val defaultExpr = p.getDefault()
@@ -131,7 +143,7 @@ case class CreateSQLFunctionCommand(
}
Cast(defaultPlan, p.dataType)
}
- }, p.name)(qualifier = qualifier))
+ }, p.name)(qualifier = qualifier, explicitMetadata =
funcInputMetadata))
Project(input, OneRowRelation())
} else {
OneRowRelation()
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence-legacy.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence-legacy.sql.out
new file mode 100644
index 000000000000..4b5ed0896741
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence-legacy.sql.out
@@ -0,0 +1,127 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_user AS SELECT 'admin.admin' AS current_user
+-- !query analysis
+CreateViewCommand `v_user`, SELECT 'admin.admin' AS current_user, false, true,
LocalTempView, UNSUPPORTED, true
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_time AS SELECT CAST(0 AS INT) AS
current_time
+-- !query analysis
+CreateViewCommand `v_time`, SELECT CAST(0 AS INT) AS current_time, false,
true, LocalTempView, UNSUPPORTED, true
+ +- Project [cast(0 as int) AS current_time#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT current_user FROM v_user
+-- !query analysis
+Project [current_user#x]
++- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT current_time FROM v_time
+-- !query analysis
+Project [current_time#x]
++- SubqueryAlias v_time
+ +- View (`v_time`, [current_time#x])
+ +- Project [cast(current_time#x as int) AS current_time#x]
+ +- Project [cast(0 as int) AS current_time#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT 'abc' AS current_user, current_user = current_user() AS function_won
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT (SELECT current_user) = current_user() AS function_won FROM v_user
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+DECLARE current_user = 'abc'
+-- !query analysis
+CreateVariable default(abc, sql=''abc''), false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx,
session.current_user
+
+
+-- !query
+SELECT current_user, current_user FROM v_user
+-- !query analysis
+Project [current_user#x, current_user#x]
++- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+DROP TEMPORARY VARIABLE current_user
+-- !query analysis
+DropVariable false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx,
session.current_user
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_date)
+SELECT typeof((SELECT current_date)) FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_timestamp)
+SELECT typeof((SELECT current_timestamp)) FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS user)
+SELECT (SELECT user) = current_user() AS function_won FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS session_user)
+SELECT (SELECT session_user) = current_user() AS function_won FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT typeof(grouping__id) FROM v_user GROUP BY current_user GROUPING SETS
((current_user))
+-- !query analysis
+Aggregate [current_user#x, spark_grouping_id#xL],
[typeof(spark_grouping_id#xL) AS typeof(grouping_id())#x]
++- Expand [[current_user#x, current_user#x, 0]], [current_user#x,
current_user#x, spark_grouping_id#xL]
+ +- Project [current_user#x, current_user#x AS current_user#x]
+ +- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+DROP VIEW v_user
+-- !query analysis
+DropTempViewCommand v_user, false
+
+
+-- !query
+DROP VIEW v_time
+-- !query analysis
+DropTempViewCommand v_time, false
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence.sql.out
new file mode 100644
index 000000000000..4b5ed0896741
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/parameterless-function-name-precedence.sql.out
@@ -0,0 +1,127 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_user AS SELECT 'admin.admin' AS current_user
+-- !query analysis
+CreateViewCommand `v_user`, SELECT 'admin.admin' AS current_user, false, true,
LocalTempView, UNSUPPORTED, true
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_time AS SELECT CAST(0 AS INT) AS
current_time
+-- !query analysis
+CreateViewCommand `v_time`, SELECT CAST(0 AS INT) AS current_time, false,
true, LocalTempView, UNSUPPORTED, true
+ +- Project [cast(0 as int) AS current_time#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT current_user FROM v_user
+-- !query analysis
+Project [current_user#x]
++- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT current_time FROM v_time
+-- !query analysis
+Project [current_time#x]
++- SubqueryAlias v_time
+ +- View (`v_time`, [current_time#x])
+ +- Project [cast(current_time#x as int) AS current_time#x]
+ +- Project [cast(0 as int) AS current_time#x]
+ +- OneRowRelation
+
+
+-- !query
+SELECT 'abc' AS current_user, current_user = current_user() AS function_won
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT (SELECT current_user) = current_user() AS function_won FROM v_user
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+DECLARE current_user = 'abc'
+-- !query analysis
+CreateVariable default(abc, sql=''abc''), false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx,
session.current_user
+
+
+-- !query
+SELECT current_user, current_user FROM v_user
+-- !query analysis
+Project [current_user#x, current_user#x]
++- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+DROP TEMPORARY VARIABLE current_user
+-- !query analysis
+DropVariable false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx,
session.current_user
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_date)
+SELECT typeof((SELECT current_date)) FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_timestamp)
+SELECT typeof((SELECT current_timestamp)) FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS user)
+SELECT (SELECT user) = current_user() AS function_won FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS session_user)
+SELECT (SELECT session_user) = current_user() AS function_won FROM t1
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+SELECT typeof(grouping__id) FROM v_user GROUP BY current_user GROUPING SETS
((current_user))
+-- !query analysis
+Aggregate [current_user#x, spark_grouping_id#xL],
[typeof(spark_grouping_id#xL) AS typeof(grouping_id())#x]
++- Expand [[current_user#x, current_user#x, 0]], [current_user#x,
current_user#x, spark_grouping_id#xL]
+ +- Project [current_user#x, current_user#x AS current_user#x]
+ +- SubqueryAlias v_user
+ +- View (`v_user`, [current_user#x])
+ +- Project [cast(current_user#x as string) AS current_user#x]
+ +- Project [admin.admin AS current_user#x]
+ +- OneRowRelation
+
+
+-- !query
+DROP VIEW v_user
+-- !query analysis
+DropTempViewCommand v_user, false
+
+
+-- !query
+DROP VIEW v_time
+-- !query analysis
+DropTempViewCommand v_time, false
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence-legacy.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence-legacy.sql.out
new file mode 100644
index 000000000000..04fb7715961d
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence-legacy.sql.out
@@ -0,0 +1,293 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v1 AS SELECT 1 AS x
+-- !query analysis
+CreateViewCommand `v1`, SELECT 1 AS x, false, true, LocalTempView,
UNSUPPORTED, true
+ +- Project [1 AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION identity_fn(x INT) RETURNS INT RETURN x
+-- !query analysis
+CreateSQLFunctionCommand identity_fn, x INT, INT, x, false, true, false, true
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query analysis
+Project [identity_fn(x#x) AS identity_fn(42)#x]
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION col_vs_param(x INT) RETURNS INT RETURN
(SELECT x FROM v1)
+-- !query analysis
+CreateSQLFunctionCommand col_vs_param, x INT, INT, (SELECT x FROM v1), false,
true, false, true
+
+
+-- !query
+SELECT col_vs_param(42)
+-- !query analysis
+Project [col_vs_param(x#x) AS col_vs_param(42)#x]
+: +- Project [x#x]
+: +- SubqueryAlias v1
+: +- View (`v1`, [x#x])
+: +- Project [cast(x#x as int) AS x#x]
+: +- Project [1 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param(current_user STRING)
+RETURNS STRING RETURN current_user
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param, current_user STRING, STRING,
current_user, false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param('should_be_ignored') = current_user() AS function_won
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_date(current_date INT)
+RETURNS STRING RETURN typeof(current_date)
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param_date, current_date INT, STRING,
typeof(current_date), false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param_date(42)
+-- !query analysis
+Project [paramless_vs_param_date(current_date#x) AS
paramless_vs_param_date(42)#x]
++- Project [cast(42 as int) AS current_date#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_time(current_time INT)
+RETURNS STRING RETURN typeof(current_time)
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param_time, current_time INT, STRING,
typeof(current_time), false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param_time(42)
+-- !query analysis
+Project [paramless_vs_param_time(current_time#x) AS
paramless_vs_param_time(42)#x]
++- Project [cast(42 as int) AS current_time#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_grouping(grouping__id
INT)
+RETURNS INT RETURN grouping__id
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param_grouping, grouping__id INT, INT,
grouping__id, false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param_grouping(42)
+-- !query analysis
+Project [paramless_vs_param_grouping(grouping__id#x) AS
paramless_vs_param_grouping(42)#x]
++- Project [cast(42 as int) AS grouping__id#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION lca_vs_param(x INT)
+RETURNS INT RETURN (SELECT y FROM (SELECT 999 AS x, x + 1 AS y))
+-- !query analysis
+CreateSQLFunctionCommand lca_vs_param, x INT, INT, (SELECT y FROM (SELECT 999
AS x, x + 1 AS y)), false, true, false, true
+
+
+-- !query
+SELECT lca_vs_param(42)
+-- !query analysis
+Project [lca_vs_param(x#x) AS lca_vs_param(42)#x]
+: +- Project [y#x]
+: +- SubqueryAlias __auto_generated_subquery_name
+: +- Project [x#x, (x#x + 1) AS y#x]
+: +- Project [999 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_vs_param(x INT)
+RETURNS INT RETURN (SELECT (SELECT x) FROM v1)
+-- !query analysis
+CreateSQLFunctionCommand outer_vs_param, x INT, INT, (SELECT (SELECT x) FROM
v1), false, true, false, true
+
+
+-- !query
+SELECT outer_vs_param(42)
+-- !query analysis
+Project [outer_vs_param(x#x) AS outer_vs_param(42)#x]
+: +- Project [scalar-subquery#x [x#x] AS scalarsubquery(x)#x]
+: : +- Project [outer(x#x)]
+: : +- OneRowRelation
+: +- SubqueryAlias v1
+: +- View (`v1`, [x#x])
+: +- Project [cast(x#x as int) AS x#x]
+: +- Project [1 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_param_pure(x INT)
+RETURNS INT RETURN (SELECT (SELECT x))
+-- !query analysis
+CreateSQLFunctionCommand outer_param_pure, x INT, INT, (SELECT (SELECT x)),
false, true, false, true
+
+
+-- !query
+SELECT outer_param_pure(42)
+-- !query analysis
+Project [outer_param_pure(x#x) AS outer_param_pure(42)#x]
+: +- Project [outer(x#x)]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+DECLARE x = 999
+-- !query analysis
+CreateVariable default(999, sql='999'), false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx, session.x
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query analysis
+Project [identity_fn(x#x) AS identity_fn(42)#x]
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION inner_fn(y INT) RETURNS INT RETURN x
+-- !query analysis
+CreateSQLFunctionCommand inner_fn, y INT, INT, x, false, true, false, true
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_fn(x INT) RETURNS INT RETURN
inner_fn(x)
+-- !query analysis
+CreateSQLFunctionCommand outer_fn, x INT, INT, inner_fn(x), false, true,
false, true
+
+
+-- !query
+SELECT outer_fn(42)
+-- !query analysis
+Project [outer_fn(x#x) AS outer_fn(42)#x]
++- Project [x#x, cast(x#x as int) AS y#x]
+ +- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION tvf_paramless_vs_param(current_user
STRING)
+RETURNS TABLE(c STRING) RETURN SELECT current_user AS c
+-- !query analysis
+CreateSQLFunctionCommand tvf_paramless_vs_param, current_user STRING, c
STRING, SELECT current_user AS c, true, true, false, true
+
+
+-- !query
+SELECT c = current_user() AS function_won FROM
tvf_paramless_vs_param('should_be_ignored')
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+DROP TEMPORARY VARIABLE x
+-- !query analysis
+DropVariable false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx, session.x
+
+
+-- !query
+DROP VIEW v1
+-- !query analysis
+DropTempViewCommand v1, false
+
+
+-- !query
+DROP TEMPORARY FUNCTION identity_fn
+-- !query analysis
+DropFunctionCommand identity_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION col_vs_param
+-- !query analysis
+DropFunctionCommand col_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param
+-- !query analysis
+DropFunctionCommand paramless_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_date
+-- !query analysis
+DropFunctionCommand paramless_vs_param_date, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_time
+-- !query analysis
+DropFunctionCommand paramless_vs_param_time, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_grouping
+-- !query analysis
+DropFunctionCommand paramless_vs_param_grouping, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION lca_vs_param
+-- !query analysis
+DropFunctionCommand lca_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_vs_param
+-- !query analysis
+DropFunctionCommand outer_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_param_pure
+-- !query analysis
+DropFunctionCommand outer_param_pure, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION inner_fn
+-- !query analysis
+DropFunctionCommand inner_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_fn
+-- !query analysis
+DropFunctionCommand outer_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION tvf_paramless_vs_param
+-- !query analysis
+DropFunctionCommand tvf_paramless_vs_param, false, true
diff --git
a/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence.sql.out
b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence.sql.out
new file mode 100644
index 000000000000..03e2b3c6d8cb
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/analyzer-results/sql-udf-name-precedence.sql.out
@@ -0,0 +1,320 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v1 AS SELECT 1 AS x
+-- !query analysis
+CreateViewCommand `v1`, SELECT 1 AS x, false, true, LocalTempView,
UNSUPPORTED, true
+ +- Project [1 AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION identity_fn(x INT) RETURNS INT RETURN x
+-- !query analysis
+CreateSQLFunctionCommand identity_fn, x INT, INT, x, false, true, false, true
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query analysis
+Project [identity_fn(x#x) AS identity_fn(42)#x]
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION col_vs_param(x INT) RETURNS INT RETURN
(SELECT x FROM v1)
+-- !query analysis
+CreateSQLFunctionCommand col_vs_param, x INT, INT, (SELECT x FROM v1), false,
true, false, true
+
+
+-- !query
+SELECT col_vs_param(42)
+-- !query analysis
+Project [col_vs_param(x#x) AS col_vs_param(42)#x]
+: +- Project [x#x]
+: +- SubqueryAlias v1
+: +- View (`v1`, [x#x])
+: +- Project [cast(x#x as int) AS x#x]
+: +- Project [1 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param(current_user STRING)
+RETURNS STRING RETURN current_user
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param, current_user STRING, STRING,
current_user, false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param('should_be_ignored') = current_user() AS function_won
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_date(current_date INT)
+RETURNS STRING RETURN typeof(current_date)
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param_date, current_date INT, STRING,
typeof(current_date), false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param_date(42)
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_time(current_time INT)
+RETURNS STRING RETURN typeof(current_time)
+-- !query analysis
+CreateSQLFunctionCommand paramless_vs_param_time, current_time INT, STRING,
typeof(current_time), false, true, false, true
+
+
+-- !query
+SELECT paramless_vs_param_time(42)
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_grouping(grouping__id
INT)
+RETURNS INT RETURN grouping__id
+-- !query analysis
+org.apache.spark.sql.catalyst.ExtendedAnalysisException
+{
+ "errorClass" : "UNSUPPORTED_GROUPING_EXPRESSION",
+ "sqlState" : "42K0E",
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 1,
+ "stopIndex" : 12,
+ "fragment" : "grouping__id"
+ } ]
+}
+
+
+-- !query
+SELECT paramless_vs_param_grouping(42)
+-- !query analysis
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "UNRESOLVED_ROUTINE",
+ "sqlState" : "42883",
+ "messageParameters" : {
+ "routineName" : "`paramless_vs_param_grouping`",
+ "searchPath" : "[`system`.`builtin`, `system`.`session`,
`spark_catalog`.`default`]"
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 8,
+ "stopIndex" : 38,
+ "fragment" : "paramless_vs_param_grouping(42)"
+ } ]
+}
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION lca_vs_param(x INT)
+RETURNS INT RETURN (SELECT y FROM (SELECT 999 AS x, x + 1 AS y))
+-- !query analysis
+CreateSQLFunctionCommand lca_vs_param, x INT, INT, (SELECT y FROM (SELECT 999
AS x, x + 1 AS y)), false, true, false, true
+
+
+-- !query
+SELECT lca_vs_param(42)
+-- !query analysis
+Project [lca_vs_param(x#x) AS lca_vs_param(42)#x]
+: +- Project [y#x]
+: +- SubqueryAlias __auto_generated_subquery_name
+: +- Project [x#x, (x#x + 1) AS y#x]
+: +- Project [999 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_vs_param(x INT)
+RETURNS INT RETURN (SELECT (SELECT x) FROM v1)
+-- !query analysis
+CreateSQLFunctionCommand outer_vs_param, x INT, INT, (SELECT (SELECT x) FROM
v1), false, true, false, true
+
+
+-- !query
+SELECT outer_vs_param(42)
+-- !query analysis
+Project [outer_vs_param(x#x) AS outer_vs_param(42)#x]
+: +- Project [scalar-subquery#x [x#x] AS scalarsubquery(x)#x]
+: : +- Project [outer(x#x)]
+: : +- OneRowRelation
+: +- SubqueryAlias v1
+: +- View (`v1`, [x#x])
+: +- Project [cast(x#x as int) AS x#x]
+: +- Project [1 AS x#x]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_param_pure(x INT)
+RETURNS INT RETURN (SELECT (SELECT x))
+-- !query analysis
+CreateSQLFunctionCommand outer_param_pure, x INT, INT, (SELECT (SELECT x)),
false, true, false, true
+
+
+-- !query
+SELECT outer_param_pure(42)
+-- !query analysis
+Project [outer_param_pure(x#x) AS outer_param_pure(42)#x]
+: +- Project [outer(x#x)]
+: +- OneRowRelation
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+DECLARE x = 999
+-- !query analysis
+CreateVariable default(999, sql='999'), false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx, session.x
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query analysis
+Project [identity_fn(x#x) AS identity_fn(42)#x]
++- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION inner_fn(y INT) RETURNS INT RETURN x
+-- !query analysis
+CreateSQLFunctionCommand inner_fn, y INT, INT, x, false, true, false, true
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_fn(x INT) RETURNS INT RETURN
inner_fn(x)
+-- !query analysis
+CreateSQLFunctionCommand outer_fn, x INT, INT, inner_fn(x), false, true,
false, true
+
+
+-- !query
+SELECT outer_fn(42)
+-- !query analysis
+Project [outer_fn(x#x) AS outer_fn(42)#x]
++- Project [x#x, cast(x#x as int) AS y#x]
+ +- Project [cast(42 as int) AS x#x]
+ +- OneRowRelation
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION tvf_paramless_vs_param(current_user
STRING)
+RETURNS TABLE(c STRING) RETURN SELECT current_user AS c
+-- !query analysis
+CreateSQLFunctionCommand tvf_paramless_vs_param, current_user STRING, c
STRING, SELECT current_user AS c, true, true, false, true
+
+
+-- !query
+SELECT c = current_user() AS function_won FROM
tvf_paramless_vs_param('should_be_ignored')
+-- !query analysis
+[Analyzer test output redacted due to nondeterminism]
+
+
+-- !query
+DROP TEMPORARY VARIABLE x
+-- !query analysis
+DropVariable false
++- ResolvedIdentifier
org.apache.spark.sql.catalyst.analysis.FakeSystemCatalog$@xxxxxxxx, session.x
+
+
+-- !query
+DROP VIEW v1
+-- !query analysis
+DropTempViewCommand v1, false
+
+
+-- !query
+DROP TEMPORARY FUNCTION identity_fn
+-- !query analysis
+DropFunctionCommand identity_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION col_vs_param
+-- !query analysis
+DropFunctionCommand col_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param
+-- !query analysis
+DropFunctionCommand paramless_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_date
+-- !query analysis
+DropFunctionCommand paramless_vs_param_date, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_time
+-- !query analysis
+DropFunctionCommand paramless_vs_param_time, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_grouping
+-- !query analysis
+org.apache.spark.sql.catalyst.analysis.NoSuchTempFunctionException
+{
+ "errorClass" : "ROUTINE_NOT_FOUND",
+ "sqlState" : "42883",
+ "messageParameters" : {
+ "routineName" : "`paramless_vs_param_grouping`"
+ }
+}
+
+
+-- !query
+DROP TEMPORARY FUNCTION lca_vs_param
+-- !query analysis
+DropFunctionCommand lca_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_vs_param
+-- !query analysis
+DropFunctionCommand outer_vs_param, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_param_pure
+-- !query analysis
+DropFunctionCommand outer_param_pure, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION inner_fn
+-- !query analysis
+DropFunctionCommand inner_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_fn
+-- !query analysis
+DropFunctionCommand outer_fn, false, true
+
+
+-- !query
+DROP TEMPORARY FUNCTION tvf_paramless_vs_param
+-- !query analysis
+DropFunctionCommand tvf_paramless_vs_param, false, true
diff --git
a/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence-legacy.sql
b/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence-legacy.sql
new file mode 100644
index 000000000000..b7f70266cc8f
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence-legacy.sql
@@ -0,0 +1,3 @@
+--IMPORT parameterless-function-name-precedence.sql
+
+--SET spark.sql.legacy.allowUdfParameterToShadowParameterlessFunction=true
diff --git
a/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence.sql
b/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence.sql
new file mode 100644
index 000000000000..6d2222cf3308
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/inputs/parameterless-function-name-precedence.sql
@@ -0,0 +1,48 @@
+-- Precedence between parameterless built-in functions and other resolution
candidates
+-- (column, LCA, outer reference, session variable). The outer-reference cases
for
+-- `current_time` are omitted because the value is non-deterministic; other
`current_time`
+-- patterns are covered (column-wins below, and the UDF-param case in the
companion
+-- sql-udf-name-precedence.sql).
+
+CREATE OR REPLACE TEMPORARY VIEW v_user AS SELECT 'admin.admin' AS
current_user;
+CREATE OR REPLACE TEMPORARY VIEW v_time AS SELECT CAST(0 AS INT) AS
current_time;
+
+-- Column wins over parameterless function.
+SELECT current_user FROM v_user;
+SELECT current_time FROM v_time;
+
+-- Parameterless function wins over LCA. Compared against `current_user()`
(with alias) so
+-- the golden stays stable across test envs that return different user names.
+SELECT 'abc' AS current_user, current_user = current_user() AS function_won;
+
+-- Parameterless function wins over outer reference.
+SELECT (SELECT current_user) = current_user() AS function_won FROM v_user;
+
+DECLARE current_user = 'abc';
+
+-- Column wins over both the parameterless function and the session variable.
+SELECT current_user, current_user FROM v_user;
+
+DROP TEMPORARY VARIABLE current_user;
+
+-- Parameterless function wins over outer reference (current_date /
current_timestamp).
+-- typeof keeps the golden stable across clock changes.
+WITH t1 AS (SELECT 1 AS current_date)
+SELECT typeof((SELECT current_date)) FROM t1;
+
+WITH t1 AS (SELECT 1 AS current_timestamp)
+SELECT typeof((SELECT current_timestamp)) FROM t1;
+
+-- Parameterless function wins over outer reference (user / session_user).
+WITH t1 AS (SELECT 1 AS user)
+SELECT (SELECT user) = current_user() AS function_won FROM t1;
+
+WITH t1 AS (SELECT 1 AS session_user)
+SELECT (SELECT session_user) = current_user() AS function_won FROM t1;
+
+-- grouping__id: the resolution rule applies but the function itself only
makes sense
+-- inside grouping analytics. Assert the rule fires structurally via
type/error pattern.
+SELECT typeof(grouping__id) FROM v_user GROUP BY current_user GROUPING SETS
((current_user));
+
+DROP VIEW v_user;
+DROP VIEW v_time;
diff --git
a/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence-legacy.sql
b/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence-legacy.sql
new file mode 100644
index 000000000000..6b2fb51f4e6a
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence-legacy.sql
@@ -0,0 +1,3 @@
+--IMPORT sql-udf-name-precedence.sql
+
+--SET spark.sql.legacy.allowUdfParameterToShadowParameterlessFunction=true
diff --git
a/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence.sql
b/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence.sql
new file mode 100644
index 000000000000..a96e98323a87
--- /dev/null
+++ b/sql/core/src/test/resources/sql-tests/inputs/sql-udf-name-precedence.sql
@@ -0,0 +1,96 @@
+-- Precedence between a SQL UDF parameter and other resolution candidates
(column,
+-- parameterless built-in function, LCA, outer reference, session variable,
nested UDF).
+
+CREATE OR REPLACE TEMPORARY VIEW v1 AS SELECT 1 AS x;
+CREATE OR REPLACE TEMPORARY FUNCTION identity_fn(x INT) RETURNS INT RETURN x;
+
+-- UDF parameter resolves when no column conflict.
+SELECT identity_fn(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION col_vs_param(x INT) RETURNS INT RETURN
(SELECT x FROM v1);
+
+-- Column wins over UDF parameter.
+SELECT col_vs_param(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param(current_user STRING)
+RETURNS STRING RETURN current_user;
+
+-- Parameterless function wins over UDF parameter (current_user). Comparison
against
+-- `current_user()` keeps the golden stable across envs returning different
user names.
+SELECT paramless_vs_param('should_be_ignored') = current_user() AS
function_won;
+
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_date(current_date INT)
+RETURNS STRING RETURN typeof(current_date);
+
+-- Parameterless function wins over UDF parameter (current_date): the body
returns 'date',
+-- which would be 'int' if the parameter alias had won.
+SELECT paramless_vs_param_date(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_time(current_time INT)
+RETURNS STRING RETURN typeof(current_time);
+
+-- Parameterless function wins over UDF parameter (current_time): the body
returns a
+-- time-typed value, vs 'int' if the parameter alias had won.
+SELECT paramless_vs_param_time(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_grouping(grouping__id
INT)
+RETURNS INT RETURN grouping__id;
+
+-- Parameterless function (grouping__id) wins over UDF parameter. grouping__id
outside of
+-- a GROUPING SETS context fails analysis; assert via the resulting error
class rather
+-- than a value comparison.
+SELECT paramless_vs_param_grouping(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION lca_vs_param(x INT)
+RETURNS INT RETURN (SELECT y FROM (SELECT 999 AS x, x + 1 AS y));
+
+-- LCA wins over UDF parameter (1000 = LCA won, 43 = param won).
+SELECT lca_vs_param(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION outer_vs_param(x INT)
+RETURNS INT RETURN (SELECT (SELECT x) FROM v1);
+
+-- Outer column wins over UDF parameter.
+SELECT outer_vs_param(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION outer_param_pure(x INT)
+RETURNS INT RETURN (SELECT (SELECT x));
+
+-- UDF parameter is visible via outer reference when no other binding is in
scope.
+SELECT outer_param_pure(42);
+
+DECLARE x = 999;
+
+-- UDF parameter wins over session variable.
+SELECT identity_fn(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION inner_fn(y INT) RETURNS INT RETURN x;
+CREATE OR REPLACE TEMPORARY FUNCTION outer_fn(x INT) RETURNS INT RETURN
inner_fn(x);
+
+-- Nested UDF only sees innermost scope: inner_fn resolves 'x' from session
variable (999),
+-- not outer_fn parameter (42).
+SELECT outer_fn(42);
+
+CREATE OR REPLACE TEMPORARY FUNCTION tvf_paramless_vs_param(current_user
STRING)
+RETURNS TABLE(c STRING) RETURN SELECT current_user AS c;
+
+-- Parameterless function wins over a same-named table UDF parameter. Note
this is NOT the
+-- SQL_FUNCTION_PARAMETER_ALIAS_METADATA_KEY rule: a table UDF body references
its parameter as
+-- an outer reference, so the function already wins via the pre-existing
"function beats outer
+-- reference" precedence (the legacy flag does not change this). Kept as a
regression guard.
+SELECT c = current_user() AS function_won FROM
tvf_paramless_vs_param('should_be_ignored');
+
+DROP TEMPORARY VARIABLE x;
+DROP VIEW v1;
+DROP TEMPORARY FUNCTION identity_fn;
+DROP TEMPORARY FUNCTION col_vs_param;
+DROP TEMPORARY FUNCTION paramless_vs_param;
+DROP TEMPORARY FUNCTION paramless_vs_param_date;
+DROP TEMPORARY FUNCTION paramless_vs_param_time;
+DROP TEMPORARY FUNCTION paramless_vs_param_grouping;
+DROP TEMPORARY FUNCTION lca_vs_param;
+DROP TEMPORARY FUNCTION outer_vs_param;
+DROP TEMPORARY FUNCTION outer_param_pure;
+DROP TEMPORARY FUNCTION inner_fn;
+DROP TEMPORARY FUNCTION outer_fn;
+DROP TEMPORARY FUNCTION tvf_paramless_vs_param;
diff --git
a/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence-legacy.sql.out
b/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence-legacy.sql.out
new file mode 100644
index 000000000000..c47ba461ba6c
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence-legacy.sql.out
@@ -0,0 +1,131 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_user AS SELECT 'admin.admin' AS current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_time AS SELECT CAST(0 AS INT) AS
current_time
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT current_user FROM v_user
+-- !query schema
+struct<current_user:string>
+-- !query output
+admin.admin
+
+
+-- !query
+SELECT current_time FROM v_time
+-- !query schema
+struct<current_time:int>
+-- !query output
+0
+
+
+-- !query
+SELECT 'abc' AS current_user, current_user = current_user() AS function_won
+-- !query schema
+struct<current_user:string,function_won:boolean>
+-- !query output
+abc true
+
+
+-- !query
+SELECT (SELECT current_user) = current_user() AS function_won FROM v_user
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+DECLARE current_user = 'abc'
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT current_user, current_user FROM v_user
+-- !query schema
+struct<current_user:string,current_user:string>
+-- !query output
+admin.admin admin.admin
+
+
+-- !query
+DROP TEMPORARY VARIABLE current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_date)
+SELECT typeof((SELECT current_date)) FROM t1
+-- !query schema
+struct<typeof(scalarsubquery()):string>
+-- !query output
+date
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_timestamp)
+SELECT typeof((SELECT current_timestamp)) FROM t1
+-- !query schema
+struct<typeof(scalarsubquery()):string>
+-- !query output
+timestamp
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS user)
+SELECT (SELECT user) = current_user() AS function_won FROM t1
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS session_user)
+SELECT (SELECT session_user) = current_user() AS function_won FROM t1
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+SELECT typeof(grouping__id) FROM v_user GROUP BY current_user GROUPING SETS
((current_user))
+-- !query schema
+struct<typeof(grouping_id()):string>
+-- !query output
+bigint
+
+
+-- !query
+DROP VIEW v_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP VIEW v_time
+-- !query schema
+struct<>
+-- !query output
+
diff --git
a/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence.sql.out
b/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence.sql.out
new file mode 100644
index 000000000000..c47ba461ba6c
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/results/parameterless-function-name-precedence.sql.out
@@ -0,0 +1,131 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_user AS SELECT 'admin.admin' AS current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v_time AS SELECT CAST(0 AS INT) AS
current_time
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT current_user FROM v_user
+-- !query schema
+struct<current_user:string>
+-- !query output
+admin.admin
+
+
+-- !query
+SELECT current_time FROM v_time
+-- !query schema
+struct<current_time:int>
+-- !query output
+0
+
+
+-- !query
+SELECT 'abc' AS current_user, current_user = current_user() AS function_won
+-- !query schema
+struct<current_user:string,function_won:boolean>
+-- !query output
+abc true
+
+
+-- !query
+SELECT (SELECT current_user) = current_user() AS function_won FROM v_user
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+DECLARE current_user = 'abc'
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT current_user, current_user FROM v_user
+-- !query schema
+struct<current_user:string,current_user:string>
+-- !query output
+admin.admin admin.admin
+
+
+-- !query
+DROP TEMPORARY VARIABLE current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_date)
+SELECT typeof((SELECT current_date)) FROM t1
+-- !query schema
+struct<typeof(scalarsubquery()):string>
+-- !query output
+date
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS current_timestamp)
+SELECT typeof((SELECT current_timestamp)) FROM t1
+-- !query schema
+struct<typeof(scalarsubquery()):string>
+-- !query output
+timestamp
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS user)
+SELECT (SELECT user) = current_user() AS function_won FROM t1
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+WITH t1 AS (SELECT 1 AS session_user)
+SELECT (SELECT session_user) = current_user() AS function_won FROM t1
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+SELECT typeof(grouping__id) FROM v_user GROUP BY current_user GROUPING SETS
((current_user))
+-- !query schema
+struct<typeof(grouping_id()):string>
+-- !query output
+bigint
+
+
+-- !query
+DROP VIEW v_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP VIEW v_time
+-- !query schema
+struct<>
+-- !query output
+
diff --git
a/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence-legacy.sql.out
b/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence-legacy.sql.out
new file mode 100644
index 000000000000..92d2370e2b98
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence-legacy.sql.out
@@ -0,0 +1,327 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v1 AS SELECT 1 AS x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION identity_fn(x INT) RETURNS INT RETURN x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query schema
+struct<identity_fn(42):int>
+-- !query output
+42
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION col_vs_param(x INT) RETURNS INT RETURN
(SELECT x FROM v1)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT col_vs_param(42)
+-- !query schema
+struct<col_vs_param(42):int>
+-- !query output
+1
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param(current_user STRING)
+RETURNS STRING RETURN current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param('should_be_ignored') = current_user() AS function_won
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+false
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_date(current_date INT)
+RETURNS STRING RETURN typeof(current_date)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param_date(42)
+-- !query schema
+struct<paramless_vs_param_date(42):string>
+-- !query output
+int
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_time(current_time INT)
+RETURNS STRING RETURN typeof(current_time)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param_time(42)
+-- !query schema
+struct<paramless_vs_param_time(42):string>
+-- !query output
+int
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_grouping(grouping__id
INT)
+RETURNS INT RETURN grouping__id
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param_grouping(42)
+-- !query schema
+struct<paramless_vs_param_grouping(42):int>
+-- !query output
+42
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION lca_vs_param(x INT)
+RETURNS INT RETURN (SELECT y FROM (SELECT 999 AS x, x + 1 AS y))
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT lca_vs_param(42)
+-- !query schema
+struct<lca_vs_param(42):int>
+-- !query output
+1000
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_vs_param(x INT)
+RETURNS INT RETURN (SELECT (SELECT x) FROM v1)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_vs_param(42)
+-- !query schema
+struct<outer_vs_param(42):int>
+-- !query output
+1
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_param_pure(x INT)
+RETURNS INT RETURN (SELECT (SELECT x))
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_param_pure(42)
+-- !query schema
+struct<outer_param_pure(42):int>
+-- !query output
+42
+
+
+-- !query
+DECLARE x = 999
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query schema
+struct<identity_fn(42):int>
+-- !query output
+42
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION inner_fn(y INT) RETURNS INT RETURN x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_fn(x INT) RETURNS INT RETURN
inner_fn(x)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_fn(42)
+-- !query schema
+struct<outer_fn(42):int>
+-- !query output
+999
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION tvf_paramless_vs_param(current_user
STRING)
+RETURNS TABLE(c STRING) RETURN SELECT current_user AS c
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT c = current_user() AS function_won FROM
tvf_paramless_vs_param('should_be_ignored')
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+DROP TEMPORARY VARIABLE x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP VIEW v1
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION identity_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION col_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_date
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_time
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_grouping
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION lca_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_param_pure
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION inner_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION tvf_paramless_vs_param
+-- !query schema
+struct<>
+-- !query output
+
diff --git
a/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence.sql.out
b/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence.sql.out
new file mode 100644
index 000000000000..2baca91aa987
--- /dev/null
+++
b/sql/core/src/test/resources/sql-tests/results/sql-udf-name-precedence.sql.out
@@ -0,0 +1,360 @@
+-- Automatically generated by SQLQueryTestSuite
+-- !query
+CREATE OR REPLACE TEMPORARY VIEW v1 AS SELECT 1 AS x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION identity_fn(x INT) RETURNS INT RETURN x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query schema
+struct<identity_fn(42):int>
+-- !query output
+42
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION col_vs_param(x INT) RETURNS INT RETURN
(SELECT x FROM v1)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT col_vs_param(42)
+-- !query schema
+struct<col_vs_param(42):int>
+-- !query output
+1
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param(current_user STRING)
+RETURNS STRING RETURN current_user
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param('should_be_ignored') = current_user() AS function_won
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_date(current_date INT)
+RETURNS STRING RETURN typeof(current_date)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param_date(42)
+-- !query schema
+struct<paramless_vs_param_date(42):string>
+-- !query output
+date
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_time(current_time INT)
+RETURNS STRING RETURN typeof(current_time)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT paramless_vs_param_time(42)
+-- !query schema
+struct<paramless_vs_param_time(42):string>
+-- !query output
+time(6)
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION paramless_vs_param_grouping(grouping__id
INT)
+RETURNS INT RETURN grouping__id
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.sql.catalyst.ExtendedAnalysisException
+{
+ "errorClass" : "UNSUPPORTED_GROUPING_EXPRESSION",
+ "sqlState" : "42K0E",
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 1,
+ "stopIndex" : 12,
+ "fragment" : "grouping__id"
+ } ]
+}
+
+
+-- !query
+SELECT paramless_vs_param_grouping(42)
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.sql.AnalysisException
+{
+ "errorClass" : "UNRESOLVED_ROUTINE",
+ "sqlState" : "42883",
+ "messageParameters" : {
+ "routineName" : "`paramless_vs_param_grouping`",
+ "searchPath" : "[`system`.`builtin`, `system`.`session`,
`spark_catalog`.`default`]"
+ },
+ "queryContext" : [ {
+ "objectType" : "",
+ "objectName" : "",
+ "startIndex" : 8,
+ "stopIndex" : 38,
+ "fragment" : "paramless_vs_param_grouping(42)"
+ } ]
+}
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION lca_vs_param(x INT)
+RETURNS INT RETURN (SELECT y FROM (SELECT 999 AS x, x + 1 AS y))
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT lca_vs_param(42)
+-- !query schema
+struct<lca_vs_param(42):int>
+-- !query output
+1000
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_vs_param(x INT)
+RETURNS INT RETURN (SELECT (SELECT x) FROM v1)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_vs_param(42)
+-- !query schema
+struct<outer_vs_param(42):int>
+-- !query output
+1
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_param_pure(x INT)
+RETURNS INT RETURN (SELECT (SELECT x))
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_param_pure(42)
+-- !query schema
+struct<outer_param_pure(42):int>
+-- !query output
+42
+
+
+-- !query
+DECLARE x = 999
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT identity_fn(42)
+-- !query schema
+struct<identity_fn(42):int>
+-- !query output
+42
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION inner_fn(y INT) RETURNS INT RETURN x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION outer_fn(x INT) RETURNS INT RETURN
inner_fn(x)
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT outer_fn(42)
+-- !query schema
+struct<outer_fn(42):int>
+-- !query output
+999
+
+
+-- !query
+CREATE OR REPLACE TEMPORARY FUNCTION tvf_paramless_vs_param(current_user
STRING)
+RETURNS TABLE(c STRING) RETURN SELECT current_user AS c
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+SELECT c = current_user() AS function_won FROM
tvf_paramless_vs_param('should_be_ignored')
+-- !query schema
+struct<function_won:boolean>
+-- !query output
+true
+
+
+-- !query
+DROP TEMPORARY VARIABLE x
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP VIEW v1
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION identity_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION col_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_date
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_time
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION paramless_vs_param_grouping
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.sql.catalyst.analysis.NoSuchTempFunctionException
+{
+ "errorClass" : "ROUTINE_NOT_FOUND",
+ "sqlState" : "42883",
+ "messageParameters" : {
+ "routineName" : "`paramless_vs_param_grouping`"
+ }
+}
+
+
+-- !query
+DROP TEMPORARY FUNCTION lca_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_vs_param
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_param_pure
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION inner_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION outer_fn
+-- !query schema
+struct<>
+-- !query output
+
+
+
+-- !query
+DROP TEMPORARY FUNCTION tvf_paramless_vs_param
+-- !query schema
+struct<>
+-- !query output
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]