MaxGekk commented on code in PR #56831:
URL: https://github.com/apache/spark/pull/56831#discussion_r3486704517


##########
sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/AttributeResolutionSuite.scala:
##########
@@ -130,6 +130,44 @@ class AttributeResolutionSuite extends SparkFunSuite {
     }
   }
 
+  test("SPARK-57725: resolution does not fail when an attribute has a null 
name") {
+    // An AttributeReference can carry a null name (e.g. from a StructField 
built with a null name
+    // via the DataFrame API). Such an attribute is unaddressable by any 
column reference -- name
+    // parts are never null -- so it must simply be skipped by the 
case-insensitive name maps
+    // rather than causing a NullPointerException in 
groupBy(_.name.toLowerCase(...)).
+    val a = AttributeReference("a", IntegerType)()
+    val nullNamed = AttributeReference(null, IntegerType)()
+
+    // Plain (no qualifier) -> exercises the `direct` map.
+    val attrs = Seq(a, nullNamed)
+    attrs.resolve(Seq("a"), resolver) match {
+      case Some(attr) => assert(attr.semanticEquals(a))
+      case _ => fail()
+    }
+    assert(attrs.resolve(Seq("b"), resolver).isEmpty)
+
+    // 2-part qualifier -> exercises the `qualified` map.
+    val qa = AttributeReference("a", IntegerType)(qualifier = Seq("ns1", "t1"))
+    val qNullNamed = AttributeReference(null, IntegerType)(qualifier = 
Seq("ns1", "t1"))
+    val qattrs = Seq(qa, qNullNamed)
+    qattrs.resolve(Seq("t1", "a"), resolver) match {
+      case Some(attr) => assert(attr.semanticEquals(qa))
+      case _ => fail()
+    }
+
+    // 3-part qualifier -> forces the `qualified3Part` (3-part lookup) and 
`qualified4Part`
+    // (4-part lookup) maps, so their population is also exercised with a 
null-named sibling.
+    val q3a = AttributeReference("a", IntegerType)(qualifier = Seq("cat", 
"db", "tbl"))
+    val q3NullNamed = AttributeReference(null, IntegerType)(qualifier = 
Seq("cat", "db", "tbl"))
+    val q3attrs = Seq(q3a, q3NullNamed)
+    Seq(Seq("db", "tbl", "a"), Seq("cat", "db", "tbl", "a")).foreach { 
nameParts =>
+      q3attrs.resolve(nameParts, resolver) match {
+        case Some(attr) => assert(attr.semanticEquals(q3a))
+        case _ => fail()
+      }
+    }
+  }

Review Comment:
   Good point. Added `SPARK-57725: resolve columns when the input plan has a 
null-named attribute` in `DataFrameSuite`. Note: the `createDataFrame` example 
from the description actually NPEs earlier in the encoder 
(`CreateNamedStruct.dataType`), a separate issue, so the new test drives the 
analyzer/`AttributeSeq.resolve` path via a `LocalRelation` carrying a 
null-named attribute instead.



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