cloud-fan commented on code in PR #53570:
URL: https://github.com/apache/spark/pull/53570#discussion_r2870494122


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionResolution.scala:
##########
@@ -19,51 +19,235 @@ package org.apache.spark.sql.catalyst.analysis
 
 import java.util.concurrent.atomic.AtomicBoolean
 
+import scala.util.control.NonFatal
+
+import org.apache.spark.internal.Logging
 import org.apache.spark.sql.AnalysisException
 import org.apache.spark.sql.catalyst.FunctionIdentifier
+import org.apache.spark.sql.catalyst.analysis.FunctionRegistry
+import org.apache.spark.sql.catalyst.catalog.SessionCatalog
 import org.apache.spark.sql.catalyst.expressions._
 import org.apache.spark.sql.catalyst.expressions.aggregate._
 import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
 import org.apache.spark.sql.connector.catalog.{
   CatalogManager,
+  CatalogNotFoundException,
+  CatalogV2Util,
   LookupCatalog
 }
+
+/**
+ * Represents the type/location of a function.
+ */
+sealed trait FunctionType
+object FunctionType {
+  /** Function is a built-in function in the builtin registry. */
+  case object Builtin extends FunctionType
+  /** Function is a temporary function in the session registry. */
+  case object Temporary extends FunctionType
+  /** Function is a persistent function in the external catalog. */
+  case object Persistent extends FunctionType
+  /** Function exists only as a table function (cannot be used in scalar 
context). */
+  case object TableOnly extends FunctionType
+  /** Function does not exist anywhere. */
+  case object NotFound extends FunctionType
+}
 import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._
 import org.apache.spark.sql.connector.catalog.functions.{
   AggregateFunction => V2AggregateFunction,
   ScalarFunction,
   UnboundFunction
 }
 import org.apache.spark.sql.errors.{DataTypeErrorsBase, QueryCompilationErrors}
+import org.apache.spark.sql.internal.SQLConf
 import org.apache.spark.sql.internal.connector.V1Function
 import org.apache.spark.sql.types._
 
 class FunctionResolution(
     override val catalogManager: CatalogManager,
     relationResolution: RelationResolution)
-    extends DataTypeErrorsBase with LookupCatalog {
+    extends DataTypeErrorsBase with LookupCatalog with Logging {
   private val v1SessionCatalog = catalogManager.v1SessionCatalog
 
   private val trimWarningEnabled = new AtomicBoolean(true)
 
-  def resolveFunction(u: UnresolvedFunction): Expression = {
-    withPosition(u) {
-      resolveBuiltinOrTempFunction(u.nameParts, u.arguments, u).getOrElse {
+  /**
+   * Produces the ordered list of fully qualified candidate names for 
resolution.
+   *
+   * @param nameParts The function name parts.
+   * @return A sequence of fully qualified function names to attempt 
resolution with.
+   */
+  private def resolutionCandidates(nameParts: Seq[String]): Seq[Seq[String]] = 
{
+    if (nameParts.size == 1) {
+      val catalogPath = catalogManager.currentCatalog.name +: 
catalogManager.currentNamespace
+      val searchPath = SQLConf.get.resolutionSearchPath(catalogPath.toSeq)
+      searchPath.map(_ ++ nameParts)
+    } else {
+      nameParts.size match {
+        case 2 if FunctionResolution.sessionNamespaceKind(nameParts).isDefined 
=>
+          // Partially qualified builtin/session: try persistent first so user 
schema wins
+          Seq(nameParts, Seq(CatalogManager.SYSTEM_CATALOG_NAME) ++ nameParts)
+        case 3 if FunctionResolution.sessionNamespaceKind(nameParts).isDefined 
=>
+          // Fully qualified system.builtin.func or system.session.func
+          Seq(nameParts)
+        case _ =>
+          Seq(nameParts)
+      }
+    }
+  }
+
+  private def resolveQualifiedFunction(
+      nameParts: Seq[String],
+      unresolvedFunc: UnresolvedFunction): Option[Expression] = {
+    if (nameParts.length == 3 &&
+        nameParts.head.equalsIgnoreCase(CatalogManager.SYSTEM_CATALOG_NAME)) {
+      // Try resolving as a session-namespace function (builtin, temp, 
extension)
+      FunctionResolution.sessionNamespaceKind(nameParts).flatMap { kind =>
+        val funcName = nameParts.last
+        val expr = v1SessionCatalog.resolveScalarFunction(kind, funcName, 
unresolvedFunc.arguments)
+        if (expr.isEmpty) {
+          if (v1SessionCatalog.lookupFunctionInfo(
+              SessionCatalog.Temp, funcName, tableFunction = true).isDefined) {

Review Comment:
   it can be builtin as well?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to