@@ -22,6 +22,7 @@ package org.apache.comet
2222import org .apache .arrow .vector ._
2323import org .apache .spark .{SparkConf , TaskContext }
2424import org .apache .spark .sql .CometTestBase
25+ import org .apache .spark .sql .api .java .UDF1
2526import org .apache .spark .sql .execution .adaptive .AdaptiveSparkPlanHelper
2627import org .apache .spark .sql .types ._
2728
@@ -269,6 +270,25 @@ class CometCodegenDispatchSmokeSuite extends CometTestBase with AdaptiveSparkPla
269270 }
270271 }
271272
273+ test(" registered Java UDF1 routes through dispatcher" ) {
274+ // Java API path: `spark.udf.register(name, UDF1<...>, returnType)`. Spark wraps the Java
275+ // functional interface in a Scala function and produces a `ScalaUDF` expression at plan
276+ // time, so the dispatcher handles it the same as a Scala-registered UDF. Sanity check that
277+ // both registration paths land on the same routing code.
278+ spark.udf.register(
279+ " javaLen" ,
280+ new UDF1 [String , Integer ] {
281+ override def call (s : String ): Integer = if (s == null ) - 1 else s.length
282+ },
283+ IntegerType )
284+ withSubjects(" abc" , " hello" , null , " x" ) {
285+ assertCodegenDidWork {
286+ checkSparkAnswerAndOperator(sql(" SELECT javaLen(s) FROM t" ))
287+ }
288+ assertKernelSignaturePresent(Seq (classOf [VarCharVector ]), IntegerType )
289+ }
290+ }
291+
272292 test(" multi-arg ScalaUDF over string + literal routes through dispatcher" ) {
273293 spark.udf.register(
274294 " prepend" ,
0 commit comments