This is an automated email from the ASF dual-hosted git repository.

sunchao 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 598a647de28f [SPARK-56840][SQL][FOLLOW-UP] Add a real NullIf repro test
598a647de28f is described below

commit 598a647de28f31e8cafe85fe4e76a7be5f26b444
Author: Chao Sun <[email protected]>
AuthorDate: Thu May 14 21:15:01 2026 -0700

    [SPARK-56840][SQL][FOLLOW-UP] Add a real NullIf repro test
    
    ### What changes were proposed in this pull request?
    
    Add a focused Catalyst regression test that constructs builtin `nullif` 
with an unresolved nested field reference while 
`ALWAYS_INLINE_COMMON_EXPR=true`. This reproduces the eager `left.dataType` 
access that motivated SPARK-56840 and guards the fixed construction path 
directly.
    
    ### Why are the changes needed?
    
    The original SPARK-56840 fix was merged with an end-to-end repro that also 
passes without the fix, so it does not prove the bug boundary. This follow-up 
adds a real negative/positive regression test that fails before commit 
`5949ab30b41` with `Invalid call to dataType on unresolved object` and passes 
with the fix.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    - `build/sbt 'catalyst/testOnly 
org.apache.spark.sql.catalyst.expressions.NullExpressionsSuite -- -z "NullIf 
accepts unresolved nested fields during inlined function construction"'`
    - Verified the same focused test fails on pre-fix parent `9ab8e43a940` with 
`UnresolvedException: Invalid call to dataType on unresolved object` and passes 
on current `apache/master`.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    Generated-by: Codex
    
    Closes #55883 from sunchao/dev/chao/codex/nullif-real-repro.
    
    Authored-by: Chao Sun <[email protected]>
    Signed-off-by: Chao Sun <[email protected]>
    (cherry picked from commit ffa3783fdf7caf3153b8c85a8bf4e5e4150a47c4)
    Signed-off-by: Chao Sun <[email protected]>
---
 .../catalyst/expressions/NullExpressionsSuite.scala    | 18 ++++++++++++++++--
 .../spark/sql/catalyst/optimizer/OptimizerSuite.scala  |  2 +-
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/NullExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/NullExpressionsSuite.scala
index bb4aed9b4002..5c19e69cdfa3 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/NullExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/NullExpressionsSuite.scala
@@ -20,7 +20,8 @@ package org.apache.spark.sql.catalyst.expressions
 import java.sql.Timestamp
 
 import org.apache.spark.{SparkFunSuite, SparkRuntimeException}
-import org.apache.spark.sql.catalyst.analysis.SimpleAnalyzer
+import org.apache.spark.sql.catalyst.FunctionIdentifier
+import org.apache.spark.sql.catalyst.analysis.{FunctionRegistry, 
SimpleAnalyzer, UnresolvedAttribute}
 import org.apache.spark.sql.catalyst.expressions.codegen.CodegenContext
 import org.apache.spark.sql.catalyst.expressions.objects.AssertNotNull
 import org.apache.spark.sql.catalyst.plans.logical.{LocalRelation, Project}
@@ -143,7 +144,7 @@ class NullExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     assert(analyze(new Nvl(floatLit, doubleLit)).dataType == DoubleType)
   }
 
-  test("NullIf replacement preserves its data type before type coercion") {
+  test("SPARK-56840: NullIf replacement preserves its data type before type 
coercion") {
     Seq(true, false).foreach { alwaysInlineCommonExpr =>
       withSQLConf(SQLConf.ALWAYS_INLINE_COMMON_EXPR.key -> 
alwaysInlineCommonExpr.toString) {
         val nullIf = new NullIf(Literal(1), Literal(1))
@@ -153,6 +154,19 @@ class NullExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     }
   }
 
+  test(
+    "SPARK-56840: NullIf accepts unresolved nested fields during inlined 
function construction") {
+    withSQLConf(SQLConf.ALWAYS_INLINE_COMMON_EXPR.key -> "true") {
+      val nullIf = FunctionRegistry.builtin.lookupFunction(
+        FunctionIdentifier("nullif"),
+        Seq(
+          UnresolvedAttribute(Seq("c", "provider")),
+          Lower(Literal("ERROR_MULTIPLE_PROVIDERS"))))
+
+      assert(nullIf.isInstanceOf[NullIf])
+    }
+  }
+
   test("AtLeastNNonNulls") {
     val mix = Seq(Literal("x"),
       Literal.create(null, StringType),
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/OptimizerSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/OptimizerSuite.scala
index 057e4ceaf0a0..57b9df6512b5 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/OptimizerSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/OptimizerSuite.scala
@@ -335,7 +335,7 @@ class OptimizerSuite extends PlanTest {
       StructType(StructField("map", MapType(IntegerType, IntegerType, false), 
false) :: Nil))
   }
 
-  test("NullIf typed null branch is replaced with a null literal") {
+  test("SPARK-56840: NullIf typed null branch is replaced with a null 
literal") {
     val optimizer = new SimpleTestOptimizer() {
       override def defaultBatches: Seq[Batch] =
         Batch("test", fixedPoint,


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

Reply via email to