LookupFunctions Logical Rule¶
LookupFunctions
is a logical rule that the logical query plan analyzer uses to make sure that UnresolvedFunction expressions can be resolved in a logical query plan.
ResolveFunctions Logical Resolution Rule
LookupFunctions
is similar to ResolveFunctions logical resolution rule, but it is ResolveFunctions
to resolve UnresolvedFunction
expressions while LookupFunctions
is just a sanity check that a future resolution is possible if tried.
LookupFunctions
is a Catalyst rule for transforming logical plans (Rule[LogicalPlan]
).
Note
LookupFunctions
does not transform a logical plan, but simply assert that a query plan is valid with regards to functions used.
LookupFunctions
is part of Simple Sanity Check one-off batch of rules.
Demo¶
Let's use Catalyst DSL to create a logical plan with an unregistered function.
import org.apache.spark.sql.catalyst.dsl.plans._
val t1 = table("t1")
import org.apache.spark.sql.catalyst.dsl.expressions._
val f1 = 'f1.function()
val plan = t1.select(f1)
scala> println(plan.numberedTreeString)
00 'Project [unresolvedalias('f1(), None)]
01 +- 'UnresolvedRelation `t1`
Make sure the function f1
does not exist.
import org.apache.spark.sql.catalyst.FunctionIdentifier
spark.sessionState.catalog.dropFunction(FunctionIdentifier("f1"), ignoreIfNotExists = true)
assert(spark.catalog.functionExists("f1") == false)
Executing LookupFunctions
rule should end up with an AnalysisException
since there is a function (f1
) in the query plan that is not available.
import spark.sessionState.analyzer.LookupFunctions
scala> LookupFunctions.apply(plan)
org.apache.spark.sql.AnalysisException: Undefined function: 'f1'. This function is neither a registered temporary function nor a permanent function registered in the database 'default'.;
at org.apache.spark.sql.catalyst.analysis.Analyzer$LookupFunctions$$anonfun$apply$15.$anonfun$applyOrElse$100(Analyzer.scala:1893)
at org.apache.spark.sql.catalyst.analysis.package$.withPosition(package.scala:53)
at org.apache.spark.sql.catalyst.analysis.Analyzer$LookupFunctions$$anonfun$apply$15.applyOrElse(Analyzer.scala:1893)
at org.apache.spark.sql.catalyst.analysis.Analyzer$LookupFunctions$$anonfun$apply$15.applyOrElse(Analyzer.scala:1884)
...
Executing Rule¶
apply(
plan: LogicalPlan): LogicalPlan
apply
finds all UnresolvedFunction expressions (in every logical operator in the input logical plan) and requests the SessionCatalog to check if their functions exist.
apply
does nothing when a function exists, and reports a NoSuchFunctionException
otherwise (that fails logical analysis).
Undefined function: '[func]'. This function is neither a registered temporary function nor a permanent function registered in the database '[db]'.
apply
is part of the Rule abstraction.