gengliangwang commented on code in PR #53570:
URL: https://github.com/apache/spark/pull/53570#discussion_r2850390605


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/ResolverGuard.scala:
##########
@@ -345,14 +346,54 @@ class ResolverGuard(catalogManager: CatalogManager) 
extends SQLConfHelper {
     createNamedStruct.children.forall(checkExpression)
   }
 
-  private def checkUnresolvedFunction(unresolvedFunction: UnresolvedFunction) =
-    unresolvedFunction.nameParts.size == 1 &&
-    
!ResolverGuard.UNSUPPORTED_FUNCTION_NAMES.contains(unresolvedFunction.nameParts.head)
 &&
-    // UDFs are not supported
-    FunctionRegistry.functionSet.contains(
-      
FunctionIdentifier(unresolvedFunction.nameParts.head.toLowerCase(Locale.ROOT))
-    ) &&
-    unresolvedFunction.children.forall(checkExpression)
+  /**
+   * Checks if an unresolved function is supported by the single-pass analyzer.
+   *
+   * The single-pass analyzer supports built-in functions. For qualified 
function names,
+   * we allow them to pass through to the resolver, which will handle them 
appropriately.
+   * This includes:
+   * - Built-in functions: `builtin.count`, `system.builtin.count`, 
unqualified `count`
+   * - Session/temp functions: `session.my_func`, `system.session.my_func` 
(may or may not work)
+   * - Persistent functions: `catalog.db.func` (not currently supported, but 
not actively blocked)
+   *
+   * We only explicitly reject certain built-in functions that require special 
handling
+   * (lambdas, generators, etc.) via the UNSUPPORTED_FUNCTION_NAMES list.
+   *
+   * @param unresolvedFunction the unresolved function to check
+   * @return true if the function should be allowed to attempt resolution, 
false otherwise
+   */
+  private def checkUnresolvedFunction(unresolvedFunction: UnresolvedFunction) 
= {
+    val nameParts = unresolvedFunction.nameParts
+    val functionName = nameParts.last
+
+    // Only reject functions that are explicitly unsupported or not in the 
builtin registry
+    // for unqualified names. For qualified names, let the resolver attempt 
resolution.
+    val shouldReject = if (nameParts.length == 1) {
+      // Unqualified: only allow if it's a known builtin (excluding 
unsupported ones)
+      ResolverGuard.UNSUPPORTED_FUNCTION_NAMES.contains(functionName) ||
+      !FunctionRegistry.functionSet.contains(
+        FunctionIdentifier(functionName.toLowerCase(Locale.ROOT))
+      )
+    } else {
+      // Qualified: allow to pass through, let downstream resolver handle it

Review Comment:
   shall we add more rejection check here?



-- 
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